1 条题解

  • 1
    @ 2022-7-14 20:12:42
    #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
    上传者