关于环形DP
环的存储:破环为链
通俗来说,即复制一份长度为n的数列,拓展到2*n的长度,扩展后第n个数和第n+1个数相接,用链模拟环
1 2 3 4 1 2 3 4
环形dp的最终值并非同区间dp一样为dp[1][n],因为是环,所以需要从1到n循环,不断更新一个最大值,MAX=max(MAX,dp[i][i+n])
还是用存储时的例子
1 2 3 4 1 2 3 4
1 2 3 4 5 6 7 8(对应下标)
n=4,从1-4,2-6,3-7,4-8都有可能成为最大值
这部分卡了非常久(太弱)
例题:能量项链 传送门
#include<cstdio> #include<algorithm> #define MAXN 300 using namespace std; int n,tail[MAXN],head[MAXN]; int f[MAXN][MAXN]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&head[i]); head[i+n]=head[i]; } for(int i=1;i<2*n;i++) { tail[i]=head[i+1]; } tail[2*n]=head[1]; for(int len=1;len<=n;len++) { for(int i=1;i+len<=2*n;i++) { int j=i+len; for(int k=i;k<j;k++) { f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+head[i]*tail[j]*tail[k]); } } } printf("%d",f[1][n]); //问题所在 return 0; }
正解
#include<cstdio> #include<algorithm> #define MAXN 300 using namespace std; int n,ans,tail[MAXN],head[MAXN],f[MAXN][MAXN]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&head[i]); head[i+n]=head[i]; } for(int i=1;i<2*n;i++) { tail[i]=head[i+1]; } tail[2*n]=head[1]; for(int len=1;len<=n;len++) { for(int i=1;i+len<=2*n;i++) { int j=i+len; for(int k=i;k<j;k++) { f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+head[i]*tail[j]*tail[k]); } } } for(int i=1;i<=n;i++) ans=max(ans,f[i][i+n-1]); printf("%d",ans); //KEY return 0; }
浙公网安备 33010602011771号