合并石子(直线版)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]); }