code2102 石子归并2
划分dp
注意环形,需要把原数复制成两份再进行,详见:
http://www.cnblogs.com/FuTaimeng/p/5427426.html
初始条件:dp[i][i]=0
转移方程:dp[i][j] = max/min{ dp[i][u]+dp[u+1][j]+sum(i,j) }
答案:max/min{ dp[i][i+n-1] } i=1 to n+1
代码如下:
#include<iostream> #include<cstring> #define Size 105 using namespace std; int n; int a[Size]; int dp1[Size][Size];//min int dp2[Size][Size];//max int sum[Size]; inline int s(int l,int r){return sum[r]-sum[l-1];} int main(){ memset(dp1,0x3f,sizeof(dp1)); memset(dp2,-1,sizeof(dp2)); cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; a[i+n]=a[i]; } for(int i=1;i<=2*n;i++){ sum[i]=sum[i-1]+a[i]; dp1[i][i]=dp2[i][i]=0; } for(int i=1;i<n*2;i++){ dp1[i][i+1]=dp2[i][i+1]=a[i]+a[i+1]; } for(int len=3;len<=n;len++){ for(int i=1;i+len-1<=n*2;i++){ int j=i+len-1; //dp1[i][j]=min(dp1[i+1][j],dp1[i][j-1])+s(i,j); //dp2[i][j]=max(dp2[i+1][j],dp2[i][j-1])+s(i,j); for(int u=i;u<j;u++){ dp1[i][j]=min(dp1[i][j], dp1[i][u]+dp1[u+1][j]+s(i,j)); dp2[i][j]=max(dp2[i][j], dp2[i][u]+dp2[u+1][j]+s(i,j)); } //cout<<i<<","<<j<<":"<<dp1[i][j]<<" "<<dp2[i][j]<<endl; } //cout<<endl; } int ans1=0x3f3f3f3f,ans2=-0x3f3f3f3f; for(int i=1;i<=n+1;i++){ ans1=min(ans1,dp1[i][i+n-1]); ans2=max(ans2,dp2[i][i+n-1]); } cout<<ans1<<endl; cout<<ans2<<endl; return 0; }