合并石子c++

来源:互联网 发布:js让div移动 编辑:程序博客网 时间:2024/05/26 17:45
 合并石子
【问题描述】
w在一个操场上一排地摆放着N堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。
【编程任务】
w试设计一个程序,计算出将N堆石子合并成一堆的最小得分。
【输入格式】
w第一行为一个正整数N (2≤N≤100)
w以下N行,每行一个正整数,小于10000,分别表示第i堆石子的个数(1iN)
【输出格式】
w为一个正整数,即最小得分。
 
 
【输入样例】
 7
 13
 7
 8
 16
 21
 4
 18
 
【输出样例】
 239
 
 
因为题中明确要求是两堆相邻石子才可以合并,所以不能用贪心(为什么有一种喜悦感^q^)
这道题要用动态规划解决
用f[i][j]表示石堆i到石堆j的最优解。首先要设i到j之间的中间量k,那么f[i][j]就等于i——k最优解f[i][k]与k+1——j最优解f[k+1][j]的和,同时还要把i-j中所有石堆数再加上一遍,用s表示每堆石子个数。
j是由i+1——n的循环,所以每次得出的f[i][j]要和前一次的f[i][j]进行比较。
即f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1])
min用快搜就可以啦o(≧v≦)o~~
 
 
附上程序么么哒
 
<span style="color:#000000;">#include<cstdio>#include<iostream>#include<algorithm>using namespace std;int n,a[10001],f[101][101];int s(int const & a,int const & b){if(a>b)return b;else return a;}int main(){scanf("%d",&n);for(int i=1;i<=n;++i){scanf("%d",&a[i]);    a[i]=a[i]+a[i-1];}    for(int i=1;i<=n;++i)    for(int j=1;j<=n;++j)    f[i][j]=100000001;    for(int i=1;i<=n;++i)    f[i][i]=0;for(int i=n-1;i>0;--i){for(int j=i+1;j<=n;++j){for(int k=i;k<=j-1;++k)f[i][j]=s(f[i][j],f[i][k]+f[k+1][j]+a[j]-a[i-1]);}}printf("%d",f[1][n]);return 0;}</span>

和合并果子有点像但是不一样啦
 
0 0
原创粉丝点击