题目:
石子合并(一)
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
3
-
描述
- 有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。
心得:
设序列是stone[],从左往右,找一个满足stone[i-1] <= stone[i+1]的i,找到后合并stone[i]和stone[i-1],再从当前位置开始向左找最大的m,使其满足stone[m] > stone[i]+stone[i-1],插到j的后面就行。一直重复,直到只剩下一堆石子就可以了。在这个过程中,可以设stone[0]和stone[n]是数组之和。
http://www.cnblogs.com/crackpotisback/p/3851983.html
代码<C语言>:
#include<stdio.h>
int main()
{
int stone[205],a,i,n,k,m,s=0,t=0,sum,max=0;
while(scanf("%d",&n) !=EOF)
{
sum=0;//初始化
for(i=1; i<n+1; i++)
{
scanf("%d",&stone[i]);
}
for(i=1; i<n+1; i++) //将数组的和设为最大值
{
s=s+stone[i];
}
stone[0]=s;
stone[n+1]=s;
do
{
//从左向右寻找stone[i-1]<=stone[i+1]
for(i=1; i<n+1; i++)
{
if(stone[i-1]<=stone[i+1])
{
k=i;
t=stone[i]+stone[i-1];
break;
}
}
sum=sum+t;
for(i=k-1; i<n; i++)
{
stone[i]=stone[i+2];
}
for(i=k-2; i>=0; i--)
{
if(stone[i]>t)
{
m=i;
break;
}
}
for(i=n; i>=m+2; i--)
{
stone[i]=stone[i-1];
}
stone[m+1]=t;
n--;
}
while(n>1);
printf("%d\n",sum);
}
return 0;
}
int main()
{
int stone[205],a,i,n,k,m,s=0,t=0,sum,max=0;
while(scanf("%d",&n) !=EOF)
{
sum=0;//初始化
for(i=1; i<n+1; i++)
{
scanf("%d",&stone[i]);
}
for(i=1; i<n+1; i++) //将数组的和设为最大值
{
s=s+stone[i];
}
stone[0]=s;
stone[n+1]=s;
do
{
//从左向右寻找stone[i-1]<=stone[i+1]
for(i=1; i<n+1; i++)
{
if(stone[i-1]<=stone[i+1])
{
k=i;
t=stone[i]+stone[i-1];
break;
}
}
sum=sum+t;
for(i=k-1; i<n; i++)
{
stone[i]=stone[i+2];
}
for(i=k-2; i>=0; i--)
{
if(stone[i]>t)
{
m=i;
break;
}
}
for(i=n; i>=m+2; i--)
{
stone[i]=stone[i-1];
}
stone[m+1]=t;
n--;
}
while(n>1);
printf("%d\n",sum);
}
return 0;
}