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;
}
发布了33 篇原创文章 · 获赞 15 · 访问量 891

猜你喜欢

转载自blog.csdn.net/weixin_43925900/article/details/103949381
Fox
今日推荐