首页 > 代码库 > Hdu 5900 QSC and Master

Hdu 5900 QSC and Master

给出n对数keyi,vali表示当前这对数的键值和权值,可以操作将连续的两个数合并,如果满足gcd(a[i],a[i+1])>1,得到

的价值是两个数的权值和,每次合并两个数之后,这两个数就会消失,然后旁边的数会接上

比如1 2 3 4 合并了 2 3 则 剩下1 4也可以合并.

 

 

处理出任意区间内的所有数是否可以合并

对于当前的[l,r]区间,如果区间[l+1,r-1]可以合并,且gcd(a[l]+a[r])>1的话,则整个区间[l,r]可以合并,价值也就是前缀和

同理处理出其他的情况  [l,r-2] [l+1,r]

区间dp,对于当前的l,r区间,如果可以合并,则直接加上区间和

反之,则枚举一个中间值k,找出区间内最大满足情况的值

 

所以是2次dp

 

#include <bits/stdc++.h>typedef long long LL;using namespace std;int n;LL  sum[1000],a[1000],b[1000];LL  g[302][302],dp[302][302];LL gcd(LL a,LL b){    return b==0?a:gcd(b,a%b);}int main(){    int T;    scanf("%d",&T);    while(T--){        memset(a,0,sizeof a);        memset(b,0,sizeof b);        memset(sum,0,sizeof sum);        memset(g,0,sizeof g);        memset(dp,0,sizeof dp);                scanf("%d",&n);        for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);        for(int i=1;i<=n;i++) scanf("%I64d",&b[i]),sum[i]=sum[i-1]+b[i];                for(int i=1;i<=n-1;i++) if(gcd(a[i],a[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(a[l],a[r])>1 && g[l+1][r-1]) g[l][r]=1;                if(gcd(a[l],a[l+1])>1 && g[l+2][r]) g[l][r]=1;                if(gcd(a[r-1],a[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++)                         dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]);            }                        printf("%I64d\n",dp[1][n]);     }    return 0;}

 

Hdu 5900 QSC and Master