區間dp學習筆記

由於學習區間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學習

相關文章
相關標籤/搜索