1. 程式人生 > >區間動歸

區間動歸

技術 ide using color 分享 得到 open href get

石子合並

鏈接

分析:dp[i][j]表示從i順時針數j個位置的最大值,規劃方向是順推,初始時dp[i][i]=0。顯然,我們需要求出合並個數為2,3,,,,n的情況,對於dp[i][j]我們假設最後一次合並位置為k,dp[i][j]=dp[i][k]+dp[k+1][j]+sum[i,j],因為sum[i,j]表示i到j這段和,跟k取的位置無關,由此可以得到dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]),最大值同理

技術分享
 1 #include "iostream"
 2 #include "cstdio"
 3 #include "
cstring" 4 #include "string" 5 using namespace std; 6 const int maxn=200+10; 7 const int INF=1<<30; 8 int f[maxn][maxn]; //max 9 int dp[maxn][maxn]; //min 10 int sum[maxn],a[maxn]; 11 int n; 12 int main() 13 { 14 cin>>n; 15 for(int i=1;i<=n;i++){ 16 cin>>a[i]; 17 sum[i]=sum[i-1
]+a[i]; 18 } 19 for(int i=n+1;i<=2*n;i++) 20 sum[i]=sum[n]+sum[i-n]; 21 for(int i=1;i<=2*n;i++) 22 for(int j=1;j<=2*n;j++) 23 dp[i][j]=INF; 24 for(int i=1;i<=2*n;i++) dp[i][i]=0; 25 for(int l=1;l<=n;l++){ 26 for(int i=1;i<=2*n-l;i++){
27 int j=i+l; 28 for(int k=i;k<j;k++){ 29 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]); 30 } 31 } 32 } 33 memset(f,0,sizeof(f)); 34 for(int l=1;l<=n;l++){ 35 for(int i=1;i<=2*n-l;i++){ 36 int j=i+l; 37 for(int k=i;k<j;k++){ 38 f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+sum[j]-sum[i-1]); 39 } 40 } 41 } 42 int cnt=0,ans=INF; 43 for(int i=1;i<=n;i++) 44 cnt=max(f[i][i+n-1],cnt); 45 for(int i=1;i<=n;i++) 46 ans=min(dp[i][i+n-1],ans); 47 cout<<ans<<endl<<cnt<<endl; 48 }
View Code

區間動歸