石子合并问题--直线版 HRBUST - 1818
注释的部分是平行四边形优化,下面是分析的草稿
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int INF = 0x3f3f3f3f; const int N = 300; int sum[N],n; int Minval() { int dp[N][N];memset(dp,INF,sizeof(dp)); for(int i=1;i<=n;++i) dp[i][i]=0; for(int len=1;len<n;++len) for(int i=1;i<=n-len;++i) { int j=i+len; for(int k=i;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]); } printf("%d ",dp[1][n]); return dp[1][n]; } int Maxval() { int dp[N][N]; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;++i) dp[i][i]=0; for(int len=1;len<n;++len) for(int i=1;i<=n-len;++i) { int j=i+len; for(int k=i;k<j;k++) // dp[i][j]=min(dp[i][k]+dp[k+1][j])+sum[j]-sum[i];同时扩大再取小,对结果没影响 dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]); } printf("%d\n",dp[1][n]); return dp[1][n]; } int main() { while(cin>>n) { sum[0]=0; for(int i=1;i<=n;++i) { int x; cin>>x; sum[i]=sum[i-1]+x;//sum[i]代表 1-i所有数字的和 } Minval(); Maxval(); } return 0; } //int Minval() //{ // int dp[N][N]; // for(int i=1;i<=n;++i) { dp[i][i]=0; s[i][i]=i; } // for(int len=1;len<n;++len) // for(int i=1;i<=n-len;++i) // { // int j=i+len; // dp[i][j]=INF; // for(int k=s[i][j-1];k<=s[i+1][j];k++) // // dp[i][j]=min(dp[i][k]+dp[k+1][j])+sum[j]-sum[i];同时扩大再取小,对结果没影响 // if(dp[i][j]>dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]) // { // dp[i][j]=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]; // s[i][j]=k; // } // } // return dp[1][n]; //}