数列游戏

题目

洛谷

做法

考虑一整个子串可完全消除\(can[i][j]\),是有两种方法转移的:
\((can[i+1][j-1]),(can[i][k],can[k+1][j])\longrightarrow can[i][j]\)

\(dp[i][j]\)表区间\((i,j)\)能得到的最大分数
这个转移可以利用\(can\)特判,具体跟上面一样

My complete code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn=1001;
LL n;
LL dp[maxn][maxn],sum[maxn],A[maxn],B[maxn];
bool can[maxn][maxn];
int main(){
	cin>>n;
	for(LL i=1;i<=n;++i) cin>>A[i];
	for(LL i=1;i<=n;++i) cin>>B[i],sum[i]=sum[i-1]+B[i];
	for(LL i=1;i<n;++i) can[i][i+1]=(__gcd(A[i],A[i+1])!=1);
	for(LL len=4 ;len<=n;len+=2)
		for(LL l=1,r=len;r<=n;++l,++r){
		    can[l][r]|=can[l+1][r-1] & (__gcd(A[l],A[r])!=1);
		    for(LL k=l;k<r;++k)
		        can[l][r]|=can[l][k] & can[k+1][r];
		}
	for(LL len=2;len<=n;++len){
		for(LL l=1,r=len;r<=n;++l,++r){
			if(can[l][r]) dp[l][r]=sum[r]-sum[l-1];
			for(LL k=l;k<r;++k)
			    dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]);
		}
	}cout<<dp[1][n];
	return 0;
}
posted @ 2019-02-23 14:42  y2823774827y  阅读(243)  评论(0编辑  收藏  举报