由於學習區間dp以前我會floyd,因此並不難掌握ios
dp[i][j]=max/min(dp[i][j],dp[i][k]+dp[k][j])
石子合併:https://www.luogu.org/problemnew/show/P1880c++
1 #include <bits/stdc++.h> 2 #define inf 1e7 3 #define lll long long int 4 #define void inline void 5 using namespace std; 6 int n,end,dp[500][500],a[1000],sum[1000],dp1[500][500],minn=912333,maxx=-1; 7 int main(){ 8 ios::sync_with_stdio(0); 9 memset(dp,-999999,sizeof(dp)); 10 memset(dp1,9999999,sizeof(dp1));//求最大值和最小值時應記得賦初值 11 cin>>n; 12 for(int i=1;i<=n;i++) 13 { 14 cin>>a[i]; 15 sum[i]=sum[i-1]+a[i]; 16 dp[i][i]=0; //這裏是在設置邊界 後面k是能夠=i的 17 dp1[i][i]=0; 18 } 19 for(int i=1;i<=n;i++) 20 { 21 sum[i+n]=sum[i+n-1]+a[i]; 22 dp[i+n][i+n]=0; 23 dp1[i+n][i+n]=0;//這裏是在設置邊界 後面k是能夠=i的 24 25 } 26 for(int i=1;i<=n;i++){ 27 for(int j=1;j+i<=n*2;j++){//關於爲何是2*n,其實這是一個環,咱們須要破環成鏈 28 end=i+j; 29 for(int k=j;k<end;k++){ 30 dp[j][end]=max(dp[j][end],dp[j][k]+dp[k+1][end]+sum[end]-sum[j-1]); 31 dp1[j][end]=min(dp1[j][end],dp1[j][k]+dp1[k+1][end]+sum[end]-sum[j-1]);//dp轉移方程 32 } 33 } 34 } 35 for(int i=1;i<=n;i++){ 36 minn=min(minn,dp1[i][i+n-1]);但最後仍是n的長度,咱們能夠理解成爲n條鏈的最大值/最小值 37 maxx=max(maxx,dp[i][i+n-1]); 38 } 39 cout<<minn<<endl<<maxx; 40 return 0; 41 }
區間dp要想學好,建議學習floyd學習