HDU 5900 QSC and Master (区间dp,记忆化搜索)

题目链接

题意:类似消消乐,给出n组键值对,每次选择键的gcd不是1的相邻的2个合并,然后可以获得这2个键对应的值和,消去的部分后,剩下的可以看做是相邻的。比如3 2 2 3消去2 2 那么3 3就是相邻的

区间dp了,因为最终值和每次抉择是有关的,贪心是不可以的,
容易想到的是对于一个区间[i,j],枚举每一次选择的位置k,然后计算出所有的可能再取最大值,当然直接暴力,时间是不够的,原因在于计算过程中的很多次的重复计算啦,所以记忆化搜索啦,对于区间长度是1的,答案就是0,区间长度是2的,检查2个数gcd,在决定,然后区间长度大于等于3的,就是暴力算啦,因为有记忆化,所以很快的。

当然区间dp ,写出状态转移方程,一般三个for进行递推,或者用记忆化搜索。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
#define gcd __gcd
#define LL long long
const int maxn = 305;
/*
2
4
3 2 2 3
1 2 3 4

*/

int n;
LL a[maxn],b[maxn],sum[maxn];
LL dp[maxn][maxn];

LL dfs(int i,int j){
    if(i >= j) return 0;
    if(-1 != dp[i][j]) return dp[i][j];
    LL &ans = dp[i][j];
    if(j - i == 1){
        if(gcd(a[i], a[j]) == 1){
            ans = 0;
        }
        else {
            ans = b[i] + b[j];
        }
    }
    else if(sum[j-1] - sum[i] == dfs(i+1, j-1)){
        if(gcd(a[i], a[j]) == 1)
            ans = dfs(i+1,j-1);
        else
            ans = dfs(i+1,j-1) + b[i] + b[j];
    }
    else
        for(int k = i; k < j; k++){
            ans = max(ans, dfs(i,k)+dfs(k+1,j));
        }

    return ans;
}




int main(){
    int T;scanf("%d", &T);
    while(T--){
        cl(a,0);cl(b,0);
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%lld", &a[i]);
        }
        sum[0] = 0;
        for(int i = 1; i <= n; i++){
            scanf("%lld", &b[i]);
            sum[i] = sum[i-1] + b[i];
        }
        cl(dp,-1);
        printf("%lld\n", dfs(1,n));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值