题意叙述:给出一串数字和它的权值,如果相邻数字非互质(公约数不为一)则可以消除,问最大可以得到的消除数字的权值和是多少
例如 2 3 3 2,3 3消除后,2 2相邻,也可以消除
输入
3
#include<iostream>
#include<stdio.h>
#include<string.h>
#define mm(ss,b) memset((ss),b,sizeof(ss))
using namespace std;
int n;
long long int g[330][330];
long long int k[330],v[330];
long long int dp[330][330];
long long int gcd(long long int a,long long int b)
{
return b==0?a:gcd(b,a%b);
}
long long int sum[330];
int main()
{
int t;
cin>>t;
while(t--)
{
mm(sum,0);
mm(g,0);
mm(dp,0);
sum[0]=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>k[i];
}
for(int i=1;i<=n;i++)
{
cin>>v[i];
sum[i]=v[i]+sum[i-1];
}
for(int i=1;i<=n;i++)
{
if(gcd(k[i],k[i-1])>1)g[i][i-1]=1;
}
for(int len = 2;len<=n;len+=2){
for(int j=1;j+len-1<=n;j++)
{
int l=j,r=j+len-1;
if(gcd(k[l],k[r])>1 && g[l+1][r-1])g[l][r]=1;
if(gcd(k[l],k[l+1])>1 && g[l+2][r])g[l][r]=1;
if(gcd(k[r-1],k[r])>1 && g[l][r-2])g[l][r]=1;
}
}
for(int len = 2;len <= n;len++)
{
for(int j=1 ; j+len-1<=n;j++)
{
int l=j,r=j+len-1;
if(g[l][r]) dp[l][r]=sum[r]-sum[l-1];
else
{
for(int k=l;k<r;k++)
{
cout<<l<<" "<<k<<" | |"<<k+1<<" "<<r<<endl;
dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]);
}
}
}
}
// for(int i=1;i<=n;i++)
// {
// cout<<dp[1][i]<<" ";
// }
// cout<<endl;
cout<<dp[1][n]<<endl;
}
return 0;
}
3
1 2 3
1 1 1
3
1 2 4
1 1 1
4
1 3 4 3
1 1 1 1
输出
0
2
0
分析:
如果可以消除,如果一个区间能合并,例如区间i到j,i和j是非互质,且i+1到j-1合并过,则合并区间i到j,同理,i和i+1非互质,i+2到j合并过,合并;j-1和j非互质,i到j-2合并过,合并i到j;
然后计算,如果合并过,计算sum【j】- sum【i-1】;
区间dp,状态方程dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j] ;