完全背包和多重背包的混合 F - The Fewest Coins

http://poj.org/problem?id=3260

这个题目有点小难,我开始没什么头绪,感觉很乱。

后来看了题解,感觉豁然开朗。

题目大意:就是这个人去买东西,东西的价格是T,这个人拥有的纸币和数量。让你求这个人买东西的纸币量加上老板找给他的纸币量最少是多少。

这个老板用于这个人拥有的纸币种类,数量是无限。

思路:

思路就是这个人看成多重背包,老板看成完全背包,f1[i] 表示这个人花了 i 的钱用的最少的纸币。f2[i] 表示老板凑出 i 的钱用的最少的纸币。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 2e4 + 10;
int N, V;
void zeroonepack(int weight,int val,int f[])
{
    for(int i=V;i>=weight;i--)
    {
        f[i] = min(f[i], f[i - weight]+val);
        //printf("f[%d]=%d\n", i, f[i]);
    }
}

void completepack(int weight,int val,int f[])
{
    //printf("weight=%d V=%d\n", weight, V);
    for(int i=weight;i<=V;i++)
    {
        f[i] = min(f[i], f[i - weight] + val);
        //printf("f[%d]=%d\n", i, f[i]);
    }
}

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 weight[maxn], num[maxn];
int f1[maxn], f2[maxn], V1;
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=1;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;
}

猜你喜欢

转载自www.cnblogs.com/EchoZQN/p/10925113.html