编程之美 电梯优化

缘起

1
2
3
4
5
编程之美
一幢m层楼高的楼房(1层是地表),只有一部电梯,一个电梯箱中有n个人,但是每个人要去的楼层不一样
现在输入每个人要去的楼层(相同楼层一样输入,不能省略).如果电梯可以在每个人要去的目标楼层停留的话
则每个人需要走的楼梯数目之和是0.但是电梯用电有限制,所以至多能停留k次,现在要你安排一个最佳停留方案
所谓最佳是指使得所有人走楼梯的层数之和最小

分析

此题极为经典.

1
dp[i][j]表示电梯停留i次,最后一次停在j层的代价最小(则最后的答案就是dp[k][1,...,n]中的最小值)

1
2
3
4
dp[i][j] = min{1<=k<j}{dp[i-1][k]+fw(k,j)}, 1<i<=k, 1<j<=n
其中, fw(k,j)的含义是想去的楼层介于(k,j)之间的人最少上的楼层数的异动.
注意,此dp方程显然是可以滚动优化的. 即变成一维的dp方程.
dp[j] = min{1<=k<j}{dp[k]+fw[k,j]}, 1<j<=n,dp的时候j需要逆向(即从n到2)

算法复杂度显然是 O(n^2*k)的

上面为什么是 k<j ? 因为不难理解——最后停留的楼层是递增的(其实就是最高停留楼层). 而初始化是dp[1]. 即电梯停留一次的话, 并且停留在第j层, 则所有人的代价. 这是不难求出的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "stdafx.h"

#include <stdio.h>
#include <algorithm>
using namespace std;
#define LOCAL
const int maxn = 25, maxm = 105; // 最多20层楼, 最多100人
int n,m,k, dp[maxn],a[maxm]; // dp[i][j] 是电梯停留i次, 最后一次停留在第j层的最小代价,但是这里做了滚动优化

int init(int i) // 电梯停在第i层的所有人的步行次数
{
int ans = 0;
for (int k = 1; k<=m;k++)
{
if (a[k]<=i)
{
ans+=min(a[k]-1, i-a[k]);
}
else
{
ans+=a[k]-i;
}
}
return ans;
}

int fw(int x, int j) // 电梯最后停留的层次是x与j(x<j)造成的异动, 其实就是重新计算去往楼层在x层以上的人的方案.
{
int ans = 0;
for (int i = 1; i<=m; i++)
{
if (a[i]>=x) // 注意, 这包含去往的楼层在x以上, 也在j以上的
{
ans-=(a[i]-x); // 这是原先的算法
if (a[i]<=j) // 对于去往的楼层在 [x,j]中的
{
ans+=min(a[i]-x, j-a[i]);
}
else
{
ans+=a[i]-j;
}
}
}
return ans;
}

int main() {
#ifdef LOCAL
freopen("d:\\data.in", "r", stdin);
//freopen("d:\\my.out", "w", stdout);
#endif
scanf("%d%d%d", &n,&m, &k);
for (int i = 1; i<=m;i++)
{
scanf("%d", a+i);
}
for (int i = 1; i<=n; i++)
{
dp[i] = init(i);
} // 初始化
for (int i = 2; i<=k; i++) // 开始dp
{
for (int j = n; j>1; j--)
{
dp[j] = 0x3f3f3f3f;
for (int x = 1; x<j; x++)
{
dp[j] = min(dp[j], dp[x]+fw(x,j));
}
}
}
int ans = 0x3f3f3f3f;
for (int i = 1; i<=n; i++)
{
if (ans>dp[i])
{
ans = dp[i];
}
}
printf("%d\n", ans);
return 0;
}

测试数据如下(10楼的高层. 7个人, 然后是7个人想去的楼层)

1
2
10 7 3
3 10 4 5 5 6 7

答案是4,一种方案是在3、5、10 三层停留

可惜, 此题也没有提交的地方啊~ QAQ 学学思想就好了