133.石子归并 2
在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。
试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.
数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.
输出共2行,第1行为最小得分,第2行为最大得分.
4
4 4 5 9
43
54
经典的区间动态规划。
分类标签 Tags 点此展开
DP:因为石子绕成一个环,不是一条直线,所以dp[i][j]的含义应为从第i堆开始,合并j堆石子能得到的最优值
则易得状态转移方程为
dp1[i][j]=better(dp1[i][j],dp1[i][k]+dp1[(i+k-1)%n+1][j-k]+sum[i][j]);
代码:
#include
#include
using namespace std;
#include
#define INFn 101
int dpmin[INFn][INFn],dpmax[INFn][INFn],n,num[INFn],sum[INFn][INFn];
void input()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d",&num[i]);
sum[i][1]=num[i];//sum储存的是从i开始合并几堆的花费
}
for(int
j=2;j<=n;++j)
for(int i=1;i<=n;++i)
dpmin[i][1]=dpmax[i][1]=0;
}
void dp()
{
for(int
j=2;j<=n;++j)//仍然要把j循环放在外面
}
}
int main()
{
input();
dp();
int ansmax=0,ansmin=INFn*INFn*INFn;
for(int i=1;i<=n;++i)
{
if(dpmin[i][n]
ansmin=dpmin[i][n];
if(dpmax[i][n]>ansmax)
ansmax=dpmax[i][n];
}
printf("%d\n%d",ansmin,ansmax);
return 0;