Knapsack in a Globalized World

来源:互联网 发布:刷码软件 编辑:程序博客网 时间:2024/06/05 21:08

Problem descriptionGlobalization 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.

InputThe 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.
OutputOutput “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 100000000003 6Sample Input 2 2 100000000004 6
Sample Output
Sample Output 1impossibleSample Output 2possible
Problem SourceGCPC 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]]就可以,复杂度很优秀,spfa大概78ms过。

#include<iostream>#include<stdio.h>#include<queue>#include<string.h>#include<algorithm>using namespace std;typedef long long ll;ll sum,dp[1005];int n,a[30];bool vis[1005];queue<int> q;void spfa(){    memset(dp,0x3f,sizeof(dp));    dp[0]=0;    q.push(0);    while(!q.empty()){        int cur=q.front();q.pop();vis[cur]=0;        for(int i=1;i<n;i++)        if(dp[(cur+a[i])%a[0]]>dp[cur]+a[i]){            dp[(cur+a[i])%a[0]]=dp[cur]+a[i];            if(!vis[(cur+a[i])%a[0]]) vis[(cur+a[i])%a[0]]=1,q.push((cur+a[i])%a[0]);        }    }}int main(){    scanf("%d%I64d",&n,&sum);    for(int i=0;i<n;i++) scanf("%d",&a[i]);    sort(a,a+n);    spfa();   // printf("%I64d\n",dp[sum%a[0]]);    if(sum>=dp[sum%a[0]]) printf("possible\n");    else                  printf("impossible\n");}



#include<iostream>#include<stdio.h>#include<algorithm>using namespace std;typedef long long ll;int n,a[30],dp[1000005];ll sum;ll gcd(ll a,ll b){      return b==0?a:gcd(b,a%b);}bool solve(){     if(sum>a[n-1]*a[n-1]){        ll d=a[0];        for(int i=1;i<n;i++) d=gcd(d,a[i]);        if(sum%d==0) return true;        else         return false;     }     dp[sum]=1;     for(int i=0;i<n;i++)         for(int j=(int)sum;j>0;j--){              if(dp[j]&&j-a[i]>=0) dp[j-a[i]]=1;            }     if(dp[0]) return true;     return false;}int main(){    scanf("%d%I64d",&n,&sum);    for(int i=0;i<n;i++) scanf("%I64d",&a[i]);    sort(a,a+n);    if(solve()) printf("possible\n");    else        printf("impossible\n");   // cin>>n;}



原创粉丝点击