时限:1000ms 内存限制:10000K 总时限:3000ms
描述
在一个圆形操场的四周摆放着n堆石子(n<= 100),现要将石子有次序地合并成一堆。规定每次只能选取相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。编一程序,读入石子堆数n及每堆的石子数(<=20)。选择一种合并石子的方案,使得做n-1次合并,得分的总和最小; 比如有4堆石子:4 4 5 9 则最佳合并方案如下:
4 4 5 9 score: 0
8 5 9 score: 8
13 9 score: 8 + 13 = 21
22 score: 8 + 13 + 22 = 43
输入
可能有多组测试数据。 当输入n=0时结束! 第一行为石子堆数n(1<=n<=100); 第二行为n堆的石子每堆的石子数,每两个数之间用一个空格分隔。
输出
合并的最小得分,每个结果一行。
输入样例
4 4 4 5 9 0
输出样例
43
解析:这个题,,我原以为它是和矩阵连乘乘积的那个题一样,后来发现有两点不同。第一点是对于矩阵连乘的题目,num=arr[i][k]+arr[k+1][j]+row[i]*col[k]*col[j],这里一个新的arr的数是两个子项代价加起来,然后再加这两个子项算的代价,而这个摆石子是算的两个子项加起来,然后再加这两个的和。。。好吧我有点卡住了,我不知道怎么把以前的代价加进去。
像矩阵连乘那样,把对角线都设为0,算当前节点m [ i ] [ j ] 时,取其中间节点h , 然后算m[i[[j]=m[i][h]+m[h+1][j]+x,这个x为把这两个子节点连起来的代价,矩阵连乘是将 i , h , j 的维数乘起来,这里的话,应该是将当前两堆直接加起来,举个例子,如:
对于数据7,3,4,8,其产生的矩阵就应该为:
0 10 21 43
0 0 7 22
0 0 0 12
0 0 0 0
上面为第一次算法后,第一次的m[i][j]就等于stone[i]+stone[j],当进行到m[1][3]和m[2][4]时,如m[1][3]=min( m[1][1]+m[2][3]+stone[1]+stone[2]+stone[3] ,m[1][2]+m[3][3]+stone[1]+stone[2]+stone[3]),m[2][4]=min( m[2][2]+m[3][4]+stone[2]+stone[3]+stone[4] ,m[2][3]+m[4][4]+stone[1]+stone[2]+stone[3] )。
事实证明,写博客有利于整理思路!啊哈哈哈,详见代码:
#include
#include
#include
using namespace std;
int n;
int stone[100];
int m[100][100],s[100][100];//s是记录路径的
int num(int m,int n)
{
int res=0;
for(int i=m;i<=n;i++)
res+=stone[i];
return res;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
memset(stone,0,sizeof(stone));
memset(m,0,sizeof(m));
memset(s,0,sizeof(s));
for(int i=1;i<=n;i++)
{
cin>>stone[i];
}
for(int r=1;r
不过上面这个是仿照矩阵连乘写的,本题中石子是环形的,那么那个n维矩阵每一个元素都要用到了,循环里面也需加一点东西就可以。那么对于主层循环,
for(int r=1;r
for(int i=1;i<=n-r;i++)
{
m[i][i+r]=m[i][i]+m[i+1][i+r]+num(i,i+r);
s[i][i+r]=i;
for(int j=i+1;j 间隔r自然是从1到n-1不变的,对于每一个开头的 i,应该改为 i<=n 即可,算法是m[i][(i+r)%n],既可以是m[1][3],也可以是m[3][1],且这两种算法是不同的,对应的 j 应该是1 2 3和3 4 1,用统一来表示就要取余,详见代码:
#include
#include
#include
using namespace std;
int n;
int stone[100];
int m[100][100],s[100][100];//s是记录路径的
int num(int s,int t)
{
int res=0;
if(s<=t)
{
for(int i=s;i<=t;i++)
res+=stone[i];
}
else
{
for(int i=s;i>stone[i];
}
for(int r=1;r=0;j=(j+1)%n,k--)
{
if(m[i][j%n]+m[(j+1)%n][(i+r)%n]+num(i,(i+r)%n)