CSUOJ 1592 石子归并(区间DP)
2016-08-01 21:04
295 查看
1592: 石子归并
Description
现在有n堆石子,第i堆有ai个石子。现在要把这些石子合并成一堆,每次只能合并相邻两个,每次合并的代价是两堆石子的总石子数。求合并所有石子的最小代价。
Input
第一行包含一个整数T(T<=50),表示数据组数。每组数据第一行包含一个整数n(2<=n<=100),表示石子的堆数。
第二行包含n个正整数ai(ai<=100),表示每堆石子的石子数。
Output
每组数据仅一行,表示最小合并代价。
Sample Input
2 4 1 2 3 4 5 3 5 2 1 4
Sample Output
19 33
解题思路:定义dp[i][j]为从第i堆石子合并到第j堆石子所需要的最小代价,然后枚举k,则dp[i][j]等于i到k堆石子与k + 1到j堆石子合并的总代价的最小值,即dp[i][j] = min(dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]),注意循环的顺序,长串总是先调用短串,所以要将长度的循环放在外面。(据说此题还可以进行平行四边形优化,将复杂度降到O(N ^ 2),以后学到了再贴代码。。)
代码如下:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> using namespace std; const int maxn = 105; int dp[maxn][maxn],a[maxn],sum[maxn]; int main() { int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i = 1;i <= n;i++){ scanf("%d",&a[i]); sum[i] = sum[i - 1] + a[i]; } memset(dp,0,sizeof(dp)); for(int l = 1;l <= n;l++){ for(int i = 1;i <= n - l;i++){ int j = i + l; dp[i][j] = INT_MAX; for(int k = i;k <= j - 1;k++){ dp[i][j] = min(dp[i][j],dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]); } } } printf("%d\n",dp[1] ); } return 0; }
相关文章推荐
- CSU-1592 石子归并(区间dp)
- CSU 1592:石子归并(区间DP)
- 石子归并 CSU - 1592 (区间dp,线性dp)
- CSU 1592 石子归并(区间dp)
- csu 1592 石子归并(区间DP)
- CSUOJ - 1592石子归并(区间DP)
- 经典问题二.【区间dp】石子归并 51nod 1021
- 区间DP入门之 石子归并问题 NYOJ 737
- 51nod 1021 石子归并(区间dp 详细解释)
- 1021 石子归并(区间DP)
- Codevs2102[石子归并 2] 区间DP
- 区间dp模型(石子归并)
- 区间dp++ 基础题,石子归并
- [nyoj737]石子归并(区间dp入门题)
- 区间dp裸题 石子归并(不是环
- 【日常学习】【区间DP】codevs1048 石子归并题解
- 1021 石子归并(区间DP)@
- 51nod oj 1021 石子归并【区间dp】
- 石子归并 【区间DP】 Codevs1048
- 1021 石子归并 区间dp