Nyoj 737: 石子合并(一)(区间DP+四边形优化)

来源:互联网 发布:蜘蛛软件下载 编辑:程序博客网 时间:2024/04/29 22:58

石子合并(一)

时间限制:1000 ms  |  内存限制:65535 KB
难度:3
描述
    有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
输入
有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开
输出
输出总代价的最小值,占单独的一行
样例输入
31 2 3713 7 8 16 21 4 18
样例输出
9239


参考四边形优化:

http://blog.csdn.net/jaihk662/article/details/78174717

dp[i][j] = dp[i][k]+dp[k+1][j]+w[i, j]

假设现在i是固定不变的

那么方程就变成了dp[j] = dp[k]+w[k, j]符合1D/1D动态规划经典模型

可以证得它也满足四边形不等式:w(i, j)+w(i', j') <= w(i', j)+w(i, j')  (i<=i'<=j'<=j)


这样的话dp[i][j]的最优决策点k和dp[i][k-1]的最优决策点k'一定满足k>=k'

同理dp[i][j]的最优决策点k和dp[i+1][k]的最优决策点k''一定满足k<=k''

令c[i][j]为dp[i][j]的最优决策点

那么求dp[i][j]只用从c[i+1][j]枚举到c[i][j-1]即可,复杂度O(n²)


引理:

对于dp方程:dp[i][j] = dp[i][k]+dp[k+1][j]+w[i, j],假设w[i, j]满足四边形不等式

那么dp[i][j]也满足四边形不等式dp[i][j]+dp[i'][j']<=dp[i][j']+dp[i'][j]  (i<=i'<=j'<=j)

并且c[i][j]单调,也就是c[i][j]<=c[i+1][j]<=c[i+1][j+1]

#include<stdio.h>#include<string.h>int dp[205][205], c[205][205], a[205], sum[205];int main(void){int n, i, j, k;while(scanf("%d", &n)!=EOF){for(i=1;i<=n;i++){scanf("%d", &a[i]);sum[i] = sum[i-1]+a[i];}memset(dp, 62, sizeof(dp));for(i=1;i<=n;i++){dp[i][i] = 0;c[i][i] = i;}for(k=1;k<=n-1;k++){for(i=1;i+k<=n;i++){for(j=c[i][i+k-1];j<=c[i+1][i+k];j++){if(j<=i+k-1 && dp[i][j]+dp[j+1][i+k]<dp[i][i+k]){dp[i][i+k] = dp[i][j]+dp[j+1][i+k];c[i][i+k] = j;}}dp[i][i+k] += sum[i+k]-sum[i-1];}}printf("%d\n", dp[1][n]); }return 0;}


阅读全文
1 0