您的位置:首页 > 其它

石子合并(一) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆

2017-07-27 15:36 926 查看
#include <stdio.h>
#include <iostream>//状态转移方程:m(i, j) = min(m(i,k),m(k + 1,j)) + sum(i, j)(i <= k < j) 
#include <string.h>//区间型动态规划 
using namespace std;//合并石子的每个阶段必定是两堆石子的合并 
int d[201], sum[200][200], m[200][200];//m[i][j] 表示从i到j的最优解
int mer(int n) {//上个阶段到下个阶段 (尝试区间内所有石子合并方式,找出最优的两堆石子合并方式) 
int t;
for(int i = 0; i < n; i++) {//将所有划分好的区间(从i 到 j )的重量都求出了 
sum[i][i] = d[i]; 
for(int j = i + 1; j < n; j++) {
sum[i][j] = sum[i][j - 1] + d[j];
}
}
/*
//查看动态规划表格 
printf("sum[i][j]\n");
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
printf("%3d ", sum[i][j]);
}

putchar('\n');
}
*/
for(int i = 0; i < n; i++)m[i][i] = 0;//从i到i花费0 
for(int len = 2; len <= n; len++){//len控制所求区间范围,即控制区间长度
for(int i = 0; i < n - len + 1; i++){
int j = i + len - 1;
m[i][j] = m[i][i] + m[i + 1][j];
for(int k = i + 1; k < j; k++){//计算从i到j堆石子合并的最小总代价 
t = m[i][k] + m[k + 1][j];
if(m[i][j] > t)m[i][j] = t;
}
m[i][j] += sum[i][j];
}
}

/* 
//查看动态规划表格 
printf("m[i][j]\n");
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
printf("%3d ", m[i][j]);
}

putchar('\n');
}
*/ 
return m[0][n - 1];
}
int main() {
int n;
while(~scanf("%d", &n)) {
for(int i = 0; i < n; i++)scanf("%d", &d[i]);
printf("%d\n", mer(n));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐