因为学习区间dp之前我会floyd,所以并不难掌握
dp[i][j]=max/min(dp[i][j],dp[i][k]+dp[k][j])
石子合并:https://www.luogu.org/problemnew/show/P1880
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