hihoCoder 1636 Pangu and Stones
阿新 • • 發佈:2018-01-20
namespace post hoc hihocode 區間 spa mes col pre
hihoCoder 1636 Pangu and Stones
思路:區間dp.
狀態:dp[i][j][k]表示i到j區間合並成k堆石子所需的最小花費。
初始狀態:dp[i][j][j-i+1]=0
狀態轉移:
如果k等於1,dp[i][j][1]=min(dp[i][j][1],dp[i][k][s-1]+dp[k+1][j][1]+sum[j]-sum[i-1])(i<=k<j)
s從l到r,因為合並成一堆的時候是有堆數限制的
如果k大於1,dp[i][j][k]=min(dp[i][j][k],dp[i][s][k-1]+dp[s+1][j][1])(i<=s<j)
石子合並問題基本套路:先合並小區間,再合並大區間,所以第三維的s-1和1可以互換位置,因為無論怎樣,小區間的值都已經確定
代碼:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=105; const int INF=0x3f3f3f3f; int dp[N][N][N]; int a[N],sum[N]; int main(){ ios::sync_with_stdio(false); cin.tie(0); int n,l,r; while(cin>>n>>l>>r){ for(int i=1;i<=n;i++)cin>>a[i],sum[i]=sum[i-1]+a[i]; mem(dp,INF); for(int i=1;i<=n;i++){ for(int j=i;j<=n;j++) dp[i][j][j-i+1]=0; }for(int d=1;d<=n;d++){ for(int i=1;i+d-1<=n;i++){ int j=i+d-1; for(int k=i;k<j;k++){ for(int s=l;s<=r;s++){ dp[i][j][1]=min(dp[i][j][1],dp[i][k][s-1]+dp[k+1][j][1]+sum[j]-sum[i-1]); } } for(int k=2;k<=n;k++){ for(int s=i;s<j;s++){ dp[i][j][k]=min(dp[i][j][k],dp[i][s][k-1]+dp[s+1][j][1]); } } } } if(dp[1][n][1]==INF)cout<<0<<endl; else cout<<dp[1][n][1]<<endl; } return 0; }
hihoCoder 1636 Pangu and Stones