Small knapsack problem summary

Knapsack problem I have now a few simple beginner, 01 is a backpack, a backpack is full, there is a multi-pack.

They can be transformed into each of the three main foundation is 01 and a backpack full backpack.

Specific content can go to the backpack nine stresses.

Give a few examples:

A - Piggy-Bank

This is a bare 01 backpack

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#define inf64 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + 10;
int dp[maxn];
int c[maxn], val[maxn];
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int w1, w2;
        scanf("%d%d", &w1, &w2);
        int w = w2 - w1;
        int n;
        scanf("%d", &n);
        memset(dp, inf, sizeof(dp));
        dp[0] = 0;
        for (int i = 1; i <= n; i++) scanf("%d%d", &val[i], &c[i]);
        for(int i=1;i<=n;i++)
        {
            for(int j=c[i];j<=w;j++)
            {
                dp[j] = min(dp[j], dp[j - c[i]]+val[i]);
            }
        }
        if (dp[w] >= inf) printf("This is impossible.\n");
        else printf("The minimum amount of money in the piggy-bank is %d.\n", dp[w]);
    }
    return 0;
}
01 backpack

 

I - Coins

 This is a bare multiple backpack

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#define inf64 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e6 + 10;
int num[maxn], dp[maxn], val[maxn];
int N,V;

void zero(int weight,int value)
{
    for(int i=V;i>=weight;i--)
    {
        dp[i] = max(dp[i], dp[i - weight] + value);
    }
}

void all(int weight,int value)
{
    for(int i=weight;i<=V;i++)
    {
        dp[i] = max(dp[i], dp[i - weight] + value);
    }
}

void solve()
{
    int t = 1;
    int ncount = 0;
    for(int i=1;i<=N;i++)
    {
        if (num[i] * val[i] >= V) all(val[i], val[i]);
        else
        {
            t = 1;
            ncount = num[i];
            while(t<=ncount)
            {
                zero(t*val[i], t*val[i]);
                ncount -= t;
                t *= 2;
            }
            zero(ncount*val[i], ncount*val[i]);
        }
    }
}

int main()
{
    while(cin>>N>>V&&N!=0&&V!=0)
    {
        for (int i = 1; i <= N; i++) scanf("%d", &val[i]);
        for (int i = 1; i <= N; i++) scanf("%d", &num[i]);
        memset(dp, -inf, sizeof(dp));
        dp[0] = 0;
        solve();
        int ans = 0;
        for(int i=1;i<=V;i++)
        {
            if (dp[i] > 0) ans++;
            //printf("dp[%d]=%d\n",i, dp[i]);
        }
        printf("%d\n", ans);
    }
    return 0;
}
Multiple backpack

 

C - Dollar Dayz

 This is a bare 01 backpack, but this is a little bit different, this is the program dp record number.

Also note that, because of this order and has nothing to do, as long as you put things into a backpack, so this time to pay attention to the order of enumeration

First enumeration capacity, and then enumerate items; and if the order is necessary to enumerate the items related to re-enumeration capacity.

The subject first enumeration capacity.

Also note that this addition will burst long long

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e4 + 10;
typedef long long ll;
const ll inf64 = 1000000000000000000;
ll a[maxn], b[maxn];

int main()
{
    int n, k;
    while(scanf("%d%d", &n, &k)!=EOF)
    {
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        b[0] = 1;
        for(int i=1;i<=k;i++)
        {
            for(int j=i;j<=n;j++)
            {
                a[j] = a[j] + a[j - i] + (b[j] + b[j - i]) / inf64;
                b[j] = (b[j] + b[j - i]) % inf64;
            }
        }
        if (a[n] == 0) printf("%lld\n", b[n]);
        else printf("%lld%018lld\n", a[n], b[n]);
    }
    return 0;
}
Tarsus + backpack

 

E - Charlie's Change

 This is a 01 + backpack output path, the path of the output of this can be seen backpack nine stresses.

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
#include <vector>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + 10;

int dp[maxn], used[maxn], path[maxn];
int weight[4] = { 1,5,10,25 };

int main()
{
    int n, num[5];
    while(scanf("%d%d%d%d%d",&n,&num[0],&num[1],&num[2],&num[3])!=EOF)
    {
        if (n == 0 && num[0] == 0 && num[1] == 0 && num[2] == 0 && num[3] == 0) break;
        memset(dp, -inf, sizeof(dp));
        memset(path, 0, sizeof(path));
        dp[0] = 0;
        path[0] = -1;
        for(int i=0;i<4;i++)
        {
            memset(used, 0, sizeof(used));
            for(int j=weight[i];j<=n;j++)
            {
                if(dp[j-weight[i]]+1>dp[j]&&dp[j-weight[i]]>=0&&used[j-weight[i]]<num[i])
                {
                    dp[j] = dp[j - weight[i]] + 1;
                    path[j] = j - weight[i];
                    used[j] = used[j - weight[i]] + 1;
                }
            }
        }
        if (dp[n] < 0) printf("Charlie cannot buy coffee.\n");
        else
        {
            int ans[100];
            memset(ans, 0, sizeof(ans));
            while(path[n]!=-1)
            {
                ans[n - path[n]]++;
                n = path[n];
            }
            printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n", ans[weight[0]], ans[weight[1]], ans[weight[2]], ans[weight[3]]);
        }
    }
    return 0;
}
Output path 01 backpack +

 

F - The Fewest Coins

 This is a multiple hybrid backpack and completely backpack, the need for a certain degree of transformation

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 2e5 + 10;
int N, V;
int weight[maxn], num[maxn];
int f1[maxn], f2[maxn], V1;
void zeroonepack(int weight, int val, int f[]) {
    for (int i = V; i >= weight; i--) {
        f[i] = min(f[i], f[i - weight] + val);
    }
}

void completepack(int weight, int val, int f[]) {
    for (int i = weight; i <= V; i++) {
        f[i] = min(f[i], f[i - weight] + val);
    }
}

void multiplepack(int weight, int val, int count, int f[]) {
    if (count*weight >= V) completepack(weight, val, f);
    else {
        int t = 1;
        while (t < count) {
            zeroonepack(weight*t, val*t, f);
            count -= t;
            t *= 2;
        }
        zeroonepack(count*weight, count*val, f);
    }
}

int main() {
    while (scanf("%d%d", &N, &V1) != EOF) {
        int max_val = 0;
        for (int i = 1; i <= N; i++) {
            scanf("%d", &weight[i]);
            max_val = max(max_val, weight[i]);
        }
        for (int i = 1; i <= N; i++) scanf("%d", &num[i]);
        V = max_val * max_val + V1 + 10;
        memset(f1, inf, sizeof(f1));
        memset(f2, inf, sizeof(f2));
        f1[0] = 0, f2[0] = 0;
        for (int i = 1; i <= N; i++) {
            multiplepack(weight[i], 1, num[i], f1);//顾客
        }
        for (int i = 1; i <= N; i++) {
            completepack(weight[i], 1, f2);
        }
        //printf("v=%d v1=%d\n", V, V1);
        int ans = inf;
        for (int i = 0; i <= V - V1; i++) {
            if (f1[V1 + i] != inf && f2[i] != inf) {
                ans = min(f1[V1 + i] + f2[i], ans);
            }
        }
        if (ans != inf) printf("%d\n", ans);
        else printf("-1\n");
    }
    return 0;
}
Multiple backpack full backpack +

 

Guess you like

Origin www.cnblogs.com/EchoZQN/p/10929400.html