一,分析:
M层电梯K个停靠层,可将最终问题分成两种情况:1,第M层为一个停靠层次;2,第M层不作为停靠层次。第一种情况通过动态规划解出,第二种情况运用第一种情况子问题数据可以解出。
二,解法:
用数组A[1]、A[2]、...A[M]分别记录需到电梯1~M层的乘客人数;Cost[i][j]记录i层到j层之间,只有第i和第j两层可以停靠,乘客(i和j层之间所有乘客)需要爬的电梯的最少层数;F[i][j]表示1~i层电梯之间,j个楼层停靠,且第i层必须是一个停靠层的的最优解;所求解为S[M][K],即电梯总共M个层,有K个停靠层,使所有乘客所有乘客需要爬的电梯层数最少,该选择哪些层停靠?最少是多少层?
状态方程为:
S[i][j] = min{F[i][j], min{F[i-t][j] + A[i]*t + A[i-1]*(t-1) + A[i-2]*(t-2)...A[i-t+1]*1} (1 <= t <= i-j) }
解释:最外层min{}中前一部分表示第i层作为停靠层的情况,后一部分表示第i层不作为停靠层的情况
三,参考代码
unsigned int min(unsigned int *pa,unsinged int *pb)
{
return (*pa > *pb) ? *pb : *pa;
}
//i floor not being stay_floor
void i_not_stay(int i, int j, int *pstay, unsigned int *psum_min)
{
if (!pstay || !psum_min)
return ;
unsigned int local_min_1 = 0xffffffff;
int local_min_pos = -1;
int t,p;
for (t = 1; t < i - j; t++) {
unsigned int local_sum = 0;
for (p = i; p >= i - t + 1; p--) {
local_sum + = A[p] * [p - (i - t)]
}
local_sum += F[i - t][j];
if (local_sum < local_min_1) {
local_min_1 = local_sum;
local_min_pos = i - t;
}
}
*psum_min = local_min_1;
*pstay = local_min_pos;
}
//S[M][K]
unsigned int F[M]+1[K+1] = {0};
unsigned int Cost[M+1][K+1] = {0};
int main()
{
//Cost[i][j]:
int i,j,t;
for (i = 1; i < M; i++) {
for (j = i; j <= M;j++) {
Cost[i][j] = 0;
if ((j - i + 1) % 2) {
Cost[i][j] = ((i + j)/2 - i) * A[(i + j) / 2];
for (t = i; t < (i + j) / 2; t++) {
Cos[i][j] += (t - i) * A[t] * 2;
}
} else {
for (t = i; t <= (i + j) / 2; t++) {
Cost[i][j] += (t - i) * A[t] * 2;
}
}
}
//F[i][j]
for (i = 1; i <=M; i++) {
for (j = i; j<= M; j++) {
if (j == i)
F[i][j] = 0;
if (i > 1 && j == 1) {
F[i][j] = F[i-1][1] + A[i-1];
}
int t;
unsigned int local_min = 0xffffffff;
for (t = 1; t <= i-j+1; t++) {
unsigned int tmp = F[i - t][j - 1] + Cost[i - t][j];
if (tmp < local_min)
local_min = tmp;
}
F[i][j] = local_min;
}
}
int stay_floor;
unsigned int sum_min;
i_not_stay(M, K, &stay_floor, &sum_min);
S[M][K] = min(&F[M][K],&sum_min);
}