接下来就是区间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;
}