接下来就是区间dp
区间dp有个可以套模板,就是枚举区间长度,然后每个区间等于他的两个子区间相加最大/最小。。。
直接上例题。
最典型例题合并石子:http://120.78.128.11/Problem.jsp?pid=2385
直接枚举每个区间长度一层一层往上就好了,类似于归并排序。需要注意的是这个是一个环形的所以直接复制一圈就好了
#include<bits/stdc++.h> using namespace std; int a[705],sum[707]={0}; int dp[705][705]; int dfs(int ,int ); int main() { int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; a[n+i]=a[i]; } for(int i=1;i<=n+n;i++)sum[i]=sum[i-1]+a[i]; //for(int i=1;i<=n+n;i++)dp[i][i]=a[i]; for(int len=2;len<=n;len++){ for(int l=1;l+len-1<=n+n;l++){ int r=len+l-1; dp[l][r]=1e9+1; for(int k=l;k<r;k++)dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]+sum[r]-sum[l-1]); } } int ans=1e9+1; for(int i=1;i<=n;i++)ans=min(ans,dp[i][i+n-1]); cout<<ans<<endl; system("pause"); return 0; }
例题二:http://120.78.128.11/Problem.jsp?pid=2384
和例题一一样直接套模板就好了,这个也是环形的,所以也需要复制一圈就好了
#include<bits/stdc++.h> #define ll long long using namespace std; ll n,ans=0; ll a[1010]; ll dp[400][400]={0}; int main() { cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; a[i+n]=a[i+n+n]=a[i]; } for(int len=2;len<=n;len++){ for(int l=n+1;len+l-1<=n+n+n;l++){ int r=l+len-1; dp[l][r]=0; for(int k=l;k<r;k++){ dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]+a[l-1]*a[k]*a[r]); } } } for(int i=1;i<=n;i++)ans=max(dp[i+n][i+n+n-1],ans); cout<<ans<<'\n'; return 0; }