QSC and Master

来源:互联网 发布:淘宝写论文有真的嘛 编辑:程序博客网 时间:2024/06/09 23:45

http://acm.hdu.edu.cn/showproblem.php?pid=5900

QSC and Master
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 488 Accepted Submission(s): 154

Problem Description

Every school has some legends, Northeastern University is the same.

Enter from the north gate of Northeastern University,You are facing the main building of Northeastern University.Ninety-nine percent of the students have not been there,It is said that there is a monster in it.

QSCI am a curious NEU_ACMer,This is the story he told us.

It’s a certain period,QSCI am in a dark night, secretly sneaked into the East Building,hope to see the master.After a serious search,He finally saw the little master in a dark corner. The master said:

“You and I, we’re interfacing.please solve my little puzzle!

There are N pairs of numbers,Each pair consists of a key and a value,Now you need to move out some of the pairs to get the score.You can move out two continuous pairs,if and only if their keys are non coprime(their gcd is not one).The final score you get is the sum of all pair’s value which be moved out. May I ask how many points you can get the most?

The answer you give is directly related to your final exam results~The young man~”

QSC is very sad when he told the story,He failed his linear algebra that year because he didn’t work out the puzzle.

Could you solve this puzzle?

(Data range:1<=N<=300
1<=Ai.key<=1,000,000,000
0

/*题目:1009 QSC and Master链接:http://acm.hdu.edu.cn/showproblem.php?pid=5900题意:给n对数字(key,value),但且仅当相邻的两对数字的key不互质,      那么就可以把他们拿掉并且获得这两对数字对应的value和,问最多可以得到      的价值总和?思路:用区间dp是显然的,dp[i][j]=max{dp[i][k]+dp[k+1][j]},但是根据题目的特殊性,      还必须考虑先中间后两边的策略可能性,也就是dp[i][j]=max(dp[i][j],dp[i+1][j-1]+value[i]+value[j]),      当然需要一些前提条件:1.gcd(key[i],key[j])!=1; 2.i->j之间的值要全部取出;      于是有了以下转移方程:      dp[i][j]=max(  max{dp[i][k]+dp[k+1][j]},  (vis[i+1][j-1]&&gcd(key[i],key[j])!=1)?      (dp[i+1][j-1]+value[i]+value[j]):-1 );      vis[i][j] |= (vis[i][k] && vis[k+1][j]) || (vis[i+1][j-1]&&gcd(key[i],key[j])!=1);      vis[i][j]==1表明从i->j之间的数都可以拿掉,自然也是最优策略;      递推方向是区间由小到大, 边界也能自然想到,详见代码:*/#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <cstdlib>#include <string>#include <vector>using namespace std;typedef long long LL;LL dp[310][310];int vis[310][310];int n;LL data[2][310];LL gcd(LL a,LL b){    return b==0?a:gcd(b,a%b);}void to_dp(){    memset(vis,0,sizeof vis);    for (int i=0;i<n;i++){        dp[i][i]=0;//边界    }    for (int i=0;i<n-1;i++){        LL a=gcd(data[0][i],data[0][i+1]);        dp[i][i+1]=(a==1?0:(data[1][i]+data[1][i+1]));//边界        if (a!=1)  vis[i][i+1]=1;//边界    }    for (int l=2;l<n;l++){        for (int i=0;i+l<n;i++){//区间长度由小到大            int j=i+l;            dp[i][j]=0;//初值            for (int k=i;k<j;k++){//区间dp                if (dp[i][k]+dp[k+1][j] > dp[i][j]){//更新更优策略                    dp[i][j]=dp[i][k]+dp[k+1][j];                    if (vis[i][k]&&vis[k+1][j]){//可以全取                        vis[i][j]=1;                    }                }            }            if ( vis[i+1][j-1] && (gcd(data[0][i],data[0][j])!=1) ){//可以全取,肯定是最有策略,更新                vis[i][j]=1;                dp[i][j]=dp[i+1][j-1]+data[1][i]+data[1][j];            }        }    }}int main(){    int t;    scanf("%d",&t);    while (t--)    {        scanf("%d",&n);        for (int i=0;i<2;i++){            for (int j=0;j<n;j++){                scanf("%I64d",&data[i][j]);            }        }        to_dp();        printf("%I64d\n",dp[0][n-1]);    }    return 0;}
1 0
原创粉丝点击