Luogu-P1063 能量项链
题目
测试得分: 100
主要算法 : 动态规划,区间DP(环状DP)
题干:
环状区间DP板子题
应试策略:
- 确定状态f[i][j]表示的是合并i-j这几堆吸盘释放的能量的最大值
- 枚举区间长度FORa(l,1,n)
- 枚举区间开头for(int i=1,in=2*n-l+1;i<=in;i++)
- 状态转移f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+a[i].head*a[k].tail*a[j].tail);
- 更新答案 if(l==n) ans=max(ans,f[i][i+n-1]);
#include<stdio.h> #include<stdlib.h> #define FORa(i,s,e) for(int i=s;i<=e;i++) #define FORs(i,s,e) for(int i=s;i>=e;i--) using namespace std; const int N=100; struct Node{ int head,tail; }a[2*N+2]; int n,ans,f[2*N+2][2*N+2];//f[i][j]表示的是合并i-j这几堆吸盘释放的能量的最大值 inline int max(int fa,int fb){return fa>fb?fa:fb;} int main() { scanf("%d",&n); FORa(i,1,n) scanf("%d",&a[i].head),a[i+n].head=a[i].head; for(int i=1;i<2*n;i++) a[i].tail=a[i+1].head; a[2*n].tail=a[1].head; FORa(l,1,n)//枚举处理吸盘长度 { for(int i=1,in=2*n-l+1;i<=in;i++)//枚举开头 { for(int k=i,j=i+l;k<j;k++)//状态转移 f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+a[i].head*a[k].tail*a[j].tail); if(l==n) ans=max(ans,f[i][i+n-1]);//更新答案 } } printf("%d",ans); return 0; } /*4 2 3 5 10*/
总结:
- 初值
- 边界
- 状态转移