1 条题解
-
1
#include <cstdio> #include <algorithm> #define LL long long #define oo 0x3f7f7f7f using namespace std; const int nma=155; int n,val[nma],num[nma];//输入 int dso[nma],uso[nma],bo[nma];//树 int ans[nma][nma];//意义同题解 int i,j,l,r,d,t; void dsea(int t,int len,int red){//向下搜索 if(num[t]==num[l]+1){//剪枝 2 ans[l][r]=max(ans[l][r],red+val[len+1]+ans[l+1][t-1]); return; } for(int ion=dso[t];ion>=l;ion=bo[ion]){ if(red+ans[ion+1][t-1]+val[len+1+ion-l]>ans[l][r])//剪枝 1 dsea(ion,len+1,red+ans[ion+1][t-1]); } return; } void usea(int t,int len,int red){//向上搜索 if(t==l) ans[l][r]=max(ans[l][r],red+val[len]); for(int ion=uso[t];ion>=l;ion=bo[ion]){ if(red+ans[ion+1][t-1]+val[len+1+ion-l]>ans[l][r])//剪枝 1 usea(ion,len+1,red+ans[ion+1][t-1]); } if(num[t]>num[l]){//剪枝 2 if(num[t]==num[l]+1){//剪枝 2 ans[l][r]=max(ans[l][r],red+val[len+1]+ans[l+1][t-1]); return; } for(int ion=dso[t];ion>=l;ion=bo[ion]){ if(red+ans[ion+1][t-1]+val[len+1+ion-l]>ans[l][r]) dsea(ion,len+1,red+ans[ion+1][t-1]); } } return; } int main() { //freopen("1.in","r",stdin); scanf("%d",&n); for(i=1;i<=n;i++) for(j=1;j<=n;j++) ans[i][j]=-oo;//第一次动规时ans有负值. for(i=1;i<=n;i++){ scanf("%d",&val[i]); for(t=1;(t<<1)<=i;t++) val[i]=max(val[i],val[t]+val[i-t]); ans[i][i]=val[1]; ans[i+1][i]=0; } ans[1][0]=0; for(i=1;i<=n;i++){ scanf("%d",&num[i]); for(j=i-1;j;j--) if(num[j]==num[i]) { bo[i]=j; break; } for(j=i-1;j;j--) if(num[j]+1==num[i]) { dso[i]=j; break; } for(j=i-1;j;j--) if(num[j]==num[i]+1) { uso[i]=j; break; } } //以上为读入,ans初始化,建树. for(d=1;d<n;d++){ for(l=1,r=l+d;r<=n;l++,r++){ for(t=l;t<r;t++){ ans[l][r]=max(ans[l][r],ans[l][t]+ans[t+1][r]); } usea(r,1,0); } } //以上为第一次动规 for(i=1;i<=n;i++) if(ans[i][i]<0) ans[i][i]=0; for(d=1;d<n;d++){ for(l=1,r=l+d;r<=n;l++,r++){ for(t=l;t<r;t++){ ans[l][r]=max(ans[l][r],ans[l][t]+ans[t+1][r]); } } } //以上为第二次动规 printf("%d",ans[1][n]); return 0; }
- 1
信息
- ID
- 389
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者