QSC and Master 区间dp

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

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< Ai.value<=1,000,000,000)

Input
First line contains a integer T,means there are T(1≤T≤10) test case。

Each test case start with one integer N . Next line contains N integers,means Ai.key.Next line contains N integers,means Ai.value.

Output
For each test case,output the max score you could get in a line.

Sample Input
3
3
1 2 3
1 1 1
3
1 2 4
1 1 1
4
1 3 4 3
1 1 1 1

Sample Output
0
2
0

Source
2016 ACM/ICPC Asia Regional Shenyang Online

题意:
有n个数组对,其中第一个值表示key,另外一个值表示val。每一次可以拿取相邻的两个数组对,要求是其两个数组对gcd(key1,key2)!=1.取值是val1+val2,问能够拿取的最大值。

另外:
1 2 3 4
如果23取走了之后,14相当于相邻的。

分析:
思路:

这是一个典型的dp问题。
当我们要求出区间[i,j]的所有取法的最大值时,我们可以把区间[i,j]分为区间[i,k],[k+1,j]前后两部分。所以区间[i,j]的最大值为所有分段可能的最大值。
但是有一点要注意,可能最大值为中间某部分:不如当数列为:1 2 4 5,我们可以把它分为1 2和4 5,但是他们都互质,所以以上方法求得的值为0,但其实2 4 可以取出来。所以说还存在一种情况就是当[i+1,j-1]可以取出所有的数时,[i,j]的最大值为[i+1,j-1]+val[i]+val[j] (key[i],key[j]不互质)

实现:
我们在求[i,j]的最大值时要知道从i开始的长度为1,2。。区间的最大值,还有从j结尾长度为1,2。。。区间的最大值。

所以可以设dp[j][i]表示从第j个数开始的连续i个数的所有取法的最大值。然后按照上面的思路完成即可。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#define LL long long
using namespace std;

const int maxn = 510;
int key[maxn],val[maxn];
LL sum[maxn],dp[maxn][maxn];

int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}

int main()
{
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&key[i]);
        }
        sum[0] = 0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&val[i]);
            sum[i]=sum[i-1]+val[i];
        }
//        for(int i=1;i<=n;i++)
//            cout<<sum[i]<<endl;
        memset(dp,0,sizeof(dp));
        for(int i=2;i<=n;i++)
        {
            for(int j=1;j+i-1<=n;j++)
            {
                if(gcd(key[j],key[j+i-1])!=1 && (sum[j+i-2]-sum[j]==dp[j+1][i-2]))
                    dp[j][i] = val[j] + val[j+i-1] + dp[j+1][i-2];
                for(int k=j+1;k<=j+i-1;k++)
                {
                    dp[j][i] = max(dp[j][i] ,dp[j][k-j] + dp[k][i+j-k]);
                }
            }
        }
        printf("%lld\n",dp[1][n]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值