文章目录
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5900
题意:给n对数,一个key,一个value,然后如果相邻的两个key不互质,那么他们就满足条件,就阔消去这两个以获得value(消去之后他左右两个就变得相邻了),问获得的value的最大值是多少?
最开始没注意消去之后旁边的就相邻了,然后就WA了,所以用full[i][j]来记录一下这一段是不是全部都阔以消掉,如果阔以的话那么就有第一种转移:
①:dp[i][j]=max(dp[i][j],dp[i+1][j-1]+cost)
然后就是每一段区间都找一找看有没有新的相邻的两个能够消掉的
②:dp[i][j]=max(dp[i][j],dp[i][k-1]+dp[k+2][j]+cost[k][k+1]);
然后就是普通情况的转移,枚举断点,把最优的转移过来
③:dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j])
#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int maxn=300+5;
const int MOD=1e9+7;
LL a[maxn],b[maxn];
LL dp[maxn][maxn];
LL cost[maxn][maxn];//cost[i][j]表示i和j这两个的花费
bool full[maxn][maxn];//full[i][j]表示[i,j]这段全部都用了
LL sum[maxn];
int f(int i,int j)
{
if(__gcd(a[i],a[j])!=1)full[i][j]=1;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int N;
cin>>N;
for(int i=1;i<=N;i++)cin>>a[i];
for(int i=1;i<=N;i++)cin>>b[i],sum[i]=sum[i-1]+b[i];
memset(cost,0,sizeof cost);
memset(dp,0,sizeof dp);
memset(full,0,sizeof full);
for(int i=1;i<=N;i++)for(int j=i+1;j<=N;j++)if(__gcd(a[i],a[j])!=1)cost[i][j]=b[i]+b[j];
for(int i=1;i<N;i++)if(__gcd(a[i],a[i+1])!=1)full[i][i+1]=1;
for(int len=1;len<N;len++)
{
for(int i=1;i+len<=N;i++)
{
int j=i+len;
if(full[i+1][j-1])//中间已经消掉了,看两边能不能消掉
{
dp[i][j]=max(dp[i][j],dp[i+1][j-1]+cost[i][j]);
if(cost[i][j])full[i][j]=1;
}
for(int k=i;k<j;k++)//找还有没有相邻的两个阔以消掉的
{
dp[i][j]=max(dp[i][j],dp[i][k-1]+dp[k+2][j]+cost[k][k+1]);
}
for(int k=i;k<j;k++)//转移最优的
{
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);
if(dp[i][k]==sum[k]-sum[i-1])f(i,k);
if(dp[k+1][j]==sum[j]-sum[k])f(k+1,j);
if(full[i][k]&&full[k+1][j])full[i][j]=1;
}
}
}
cout<<dp[1][N]<<endl;
}
}