码迷,mamicode.com
首页 > 其他好文 > 详细

Hdu 5900 QSC and Master

时间:2016-09-24 09:20:46      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:

给出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

标签:

原文地址:http://www.cnblogs.com/foreignbill/p/5902419.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!