POJ 1787 Charlie's Change (多重背包 带结果组成)

题意:求通过c1个1分的c2个5分的c3个10分的c4个25分的组成p的最多个数并且输出分别选多少个。

分析:多重背包+一个数组保存当前最优解情况下选的个数;

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstdlib>
#include <map>
#include <vector>

using namespace std;

const int oo = 1e8;

struct C
{
    int x, num;
}c[120];

void Init(int c1, int x, int &k)
{
    int num = 1;
    while(c1>=num)
    {
        c[k].x = num*x;
        c[k++].num = num;
        c1-=num;
        num*=2;
    }
    if(c1!=0)
    {
        c[k].x = c1*x;
        c[k++].num = c1;
    }
}

bool cmp(C x1, C x2)
{
    return x1.x < x2.x;
}
int dp[10005];
int ans[10005][6];

int main()
{
    int p, c1, c2, c3, c4;
    while(scanf("%d %d %d %d %d", &p, &c1, &c2, &c3, &c4), p+c1+c2+c3+c4)
    {
        int k = 0;
        Init(c1, 1, k);
        Init(c2, 5, k);
        Init(c3, 10, k);
        Init(c4, 25, k);
        sort(c, c+k, cmp);
        memset(dp, 0, sizeof(dp));
        memset(ans, 0, sizeof(ans));
        dp[0] = 1;
        for(int i=0; i<k; i++)
        {
            for(int j=p; j>=c[i].x; j--)
            {
                if(dp[j-c[i].x]&&dp[j-c[i].x]+c[i].num > dp[j])
                {
                    dp[j] = dp[j-c[i].x]+c[i].num;
                    int x = c[i].x/c[i].num;
                    if(x==1)
                    {
                        ans[j][1] = ans[j-c[i].x][1]+c[i].num;
                        ans[j][2] = ans[j-c[i].x][2];
                        ans[j][3] = ans[j-c[i].x][3];
                        ans[j][4] = ans[j-c[i].x][4];
                    }
                    else if(x==5)
                    {
                        ans[j][2] = ans[j-c[i].x][2]+c[i].num;
                        ans[j][1] = ans[j-c[i].x][1];
                        ans[j][3] = ans[j-c[i].x][3];
                        ans[j][4] = ans[j-c[i].x][4];
                    }
                    else if(x==10)
                    {
                        ans[j][3] = ans[j-c[i].x][3]+c[i].num;
                        ans[j][2] = ans[j-c[i].x][2];
                        ans[j][1] = ans[j-c[i].x][1];
                        ans[j][4] = ans[j-c[i].x][4];
                    }
                    else
                    {
                        ans[j][4] = ans[j-c[i].x][4]+c[i].num;
                        ans[j][2] = ans[j-c[i].x][2];
                        ans[j][3] = ans[j-c[i].x][3];
                        ans[j][1] = ans[j-c[i].x][1];
                    }
                }
            }
        }
        if(dp[p]==0)
            printf("Charlie cannot buy coffee.\n");
        else
            printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",
                   ans[p][1], ans[p][2], ans[p][3], ans[p][4]);
    }

    return 0;
}

 

posted @ 2016-05-22 19:45  梦中。。  阅读(190)  评论(0编辑  收藏  举报