Fox And Jumping(01背包)

题意:有n张卡,每张卡有单独val和weight。每张卡支付一次weight就可以无限用val。val可以相加或者相减。求最少总weight来保证最后可以用买了的val凑出任何一个正整数。
解题思路:其实说了那么多,如果gcd(i,j)==1的话,那么i和j就可以凑出1(拓展欧几里得),就可以凑出任何一个正整数。
所以构建dp[i]gcd=i时,最小weight。最后输出dp[1]dp[new_gcd]=min(dp[new_gcd],new_weight);.记得用map储存dp。
错误原因:两张卡可能会有相同的val但不同的weight。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define LL long long
#define MT(a,b) memset(a,b,sizeof(a))
const int maxn=5E5+5;
const int ONF=-0x3f3f3f3f;
const int INF=0x3f3f3f3f;
map<LL,LL>dp;
LL val[3015],weight[305];
LL gcd(LL x,LL y) { return x==0?y:gcd(y%x,x);}
int main (){
    int n;
    scanf("%d",&n);
    dp.clear();
    for (int i=1;i<=n;i++)
        scanf("%lld",&val[i]);
    for (int i=1;i<=n;i++){
        scanf("%lld",&weight[i]);
        if (dp.count(val[i])==0) dp[val[i]]=weight[i];
        dp[val[i]]=min(dp[val[i]],weight[i]);
    }
    map<LL,LL>::iterator it;
    for (int i=1;i<=n;i++){
        for (it=dp.begin();it!=dp.end();it++){
            LL now_gcd=it->first,now_weight=it->second;
            LL new_gcd=gcd(now_gcd,val[i]),new_weight=now_weight+weight[i];
            if (dp.count(new_gcd)==0) dp[new_gcd]=new_weight;
            else dp[new_gcd]=min(dp[new_gcd],new_weight);
        }
    }
    if (dp.count(1)==0) printf("-1\n");
    else printf("%d\n",dp[1]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值