合并石子(直线版)tyvj1055
很菜,很菜,这么一个简单的题写了好几天!
这是网上的版本,好理解,推荐
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=1<<30;
const int maxn=310;
int s[maxn],f[maxn][maxn],n;
int main()
{
scanf("%d",&n);
int x;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
s[i]=s[i-1]+x;
f[i][i]=0;
}
for(int l=1;l<=n;l++)
for(int i=1;i<=n;i++)
{
int j=i+l;
f[i][j]=inf;
if(j>n) break;
for(int k=i;k<j;k++)
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
}
printf("%d\n",f[1][n]);
}
一本通的版本,不好写
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100;
int s[maxn],f[maxn][maxn],fm[maxn][maxn],n;
int main()
{
scanf("%d",&n);
memset(f,0x3f3f3f3f,sizeof(f));
//memset(fm,0,sizeof(fm));
int x;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
s[i]=s[i-1]+x;
f[i][i]=fm[i][i]=0;
}
for(int i=n-1;i>=1;i--)//这里必须是倒着开始的,打表即可
for(int j=i+1;j<=n;j++)
for(int k=i;k<j;k++)
//这里只能从i开始,不能从i+1开始,否则的话k+1就等于i+2了,不能存放在i和j中间
{
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
fm[i][j]=max(fm[i][j],fm[i][k]+fm[k+1][j]+s[j]-s[i-1]);
//cout<<i<<j<<k<<" "<<f[i][j]<<endl;打表的过程
}
printf("%d\n%d",f[1][n],fm[1][n]);
}

浙公网安备 33010602011771号