Knapsack in a Globalized World --多重完全背包

Knapsack in a Globalized World
Time Limit: 10000ms, Special Time Limit:25000ms, Memory Limit:65536KB
Total submit users: 27, Accepted users: 10
Problem 13790 : No special judgement
Problem description
Globalization stops at nothing, not even at the good old honest profession of a burglar. Nowadays it is not enough to break in somewhere, take everything you can carry and dart off. No! You have to be competitive, optimize your profit and utilize synergies.
So, the new game rules are:
 break only into huge stores, so there is practically endless supply of any kind of items;
 your knapsack should be huge;
 your knapsack should be full (there should be no empty space left).
Damn you, globalization, these rules are not easy to follow! Luckily, you can write a program, which will help you decide whether you should loot a store or not.


Input
The input consists of:
 one line with two integers n (1 ≤ n ≤ 20) and k (1 ≤ k ≤ 1018), where n is the number of different item types and k is the size of your knapsack;
 one line with n integers g1.... gn (1 ≤ gi ≤ 103 for all 1 ≤ i ≤ n), where g1.... gn are the sizes of the n item types.

Output
Output “possible” if it is possible to fill your knapsack with items from the store (you may assume that there are enough items of any type), otherwise output

Sample Input
Sample Input 1 
2 10000000000
3 6

Sample Input 2 
2 10000000000
4 6
Sample Output
Sample Output 1
impossible

Sample Output 2
possible
Problem Source
GCPC 2016

思路:

多重完全背包最短路做法:

对于n个数能否构成值K,我们考虑集合S'表示这n个数能构成的数的集合,显然存在如果一个数x属于S'那么x+a[i],x+2*a[i]也属于集合S',那么我们定义dp[i]%a[1]==i的时候S'中最小的数,那么所有比dp[i]大的同余类都一定属于S',而比dp[i]小的同余类一定不属于S',因此可以得到最短路模型,用dp[now]+a[i]更新dp[(dp[now]+a[i])%a[1]];跑一遍最短路即可得到所有dp[i] i的取值范围<a[1]),所以最好先sort一下,让a[1]最小。最后判别k是不是大于等于dp[k%a[1]]就可以。因为dp[i]已经是x%a[1]=i(x属于S’)的最小值了,如果K%a[1]=ik>dp[i]那么k可以由dp[i]+a[1]*r(r不定)构成自然属于S,如果小于dp[i]那么k一定不再S中,因为dp[i]已经是最小了;

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
#define INF          0x3f3f3f3f
#define sf(a)        scanf("%d",&a)
#define sff(a,b)     scanf("%d%d",&a,&b)
#define sfff(a,b,c)  scanf("%d%d%d",&a,&b,&c)
#define PI  arcos(-1)
#define esp 1e-9
typedef long long LL;
typedef double db;
const int maxn=1e3+10;
const LL mod=1e9+7;
int read()
{
    int f=1,x=0;
    char ch=getchar();
    while(ch<'0'|| ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9' && ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return f*x;
}
//================================================================
int n,a[maxn],vis[maxn];
LL dp[maxn],k;
void spfa()
{
    memset(vis,0,sizeof(vis));
    memset(dp,0x3f,sizeof(dp));
    dp[0]=0;
    queue<int> q;
    q.push(0);
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        vis[now]=0;
        for(int i=0;i<n;i++)
        {
            int tmp=(dp[now]+a[i])%a[0];
            if(dp[tmp]>dp[now]+a[i])
            {
                dp[tmp]=dp[now]+a[i];
                if(!vis[tmp])q.push(tmp);
                vis[tmp]=1;
            }
        }
    }
}





int main()
{
   // freopen("input.txt","r",stdin);
    while(scanf("%d%I64d",&n,&k)!=EOF)
    {
       for(int i=0;i<n;i++)
            scanf("%d",a+i);
       sort(a,a+n);
       spfa();
       if(k>=dp[k%a[0]])puts("possible");
       else puts("impossible");
    }
}
原文地址:https://www.cnblogs.com/MeowMeowMeow/p/7275399.html