POJ1787 完全背包 xingxing在努力

  这道题的意思是给你1 5 10 25 的硬币c1 c2 c3 c4枚, 求出一个方案使硬币个数最多, 且恰好是p..给完全背包加几个状态即可。。代码如下:

  WA点: 可能看完动漫时间有点晚记得把题目终止输入条件判错了 2:used[j-w[i]]<num[i]写错成used[j-w[i]]+1<num[i],罪过罪过:

  

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 10000 + 100;
const int inf = 0x3f3f3f3f;
int f[maxn], pre[maxn], used[maxn];  //f表示组成j的时候最多有几个硬币 pre表示前继  used表示为j时同类为多少个
int p, num[4];
int w[] = {1, 5, 10, 25};

int main()
{
    while(scanf("%d%d%d%d%d", &p, &num[0], &num[1], &num[2], &num[3])==5)
    {
        if(!(p||num[0]||num[1]||num[2]||num[3]))    break;
        for(int i=0; i<=p; i++) f[i] = -inf;
        //memset(pre, 0, sizeof(pre));
        f[0] = 0;
        pre[0] = -1;
        for(int i=0; i<4; i++)
        {
            memset(used, 0, sizeof(used));
            for(int j=w[i]; j<=p; j++)
                if(f[j-w[i]]+1>f[j] && f[j-w[i]]>=0 && used[j-w[i]]<num[i])
                {
                    f[j] = f[j-w[i]] + 1;
                    used[j] = used[j-w[i]] + 1;
                    pre[j] = j-w[i];
                }
        }
        int ans[30];
        memset(ans, 0, sizeof(ans));
        if(f[p] < 0) printf("Charlie cannot buy coffee.\n");
        else
        {
            int now = p;
            while(pre[now] != -1)
            {
                ans[now-pre[now]]++;
                now = pre[now];
            }
            printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n", ans[w[0]], ans[w[1]], ans[w[2]], ans[w[3]]);
        }
     }
    return 0;
}
时间: 2024-10-08 10:27:56

POJ1787 完全背包 xingxing在努力的相关文章

HDU2639 第k小01背包 xingxing在努力

这个题目是求解第k小01背包, 我们只需要再多加一维表示容量为j时的价值即可..代码里面用了归并排序的思想来求解f[j][k], 代码如下: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int f[1000+10][35]; int A[35], B[35]; //A选 B不选 int W[100+10], V[100+10]; int N, v, K; v

POJ2923 状态压缩01背包 xingxing在努力

这道题算是很经典的状态压缩01背包了, 题意是有一个人要用两辆小汽车搬家, 每辆小汽车都有一个最大载重量, 现在有一些要搬的家具, 告诉你这些家具的重量, 问最少几次能将这些家具搬完(每次两辆汽车必须出动, 即使有一辆车什么都没有装)? 物品个数不超过10,根据经验一般有10存在的话都要带点暴力的色彩, 那么这道题就是先要预处理所有一次搬走的家具的集合, 然后就将其转化成了01背包的问假设d[i][j]是前i个家具中搬走了j(集合)家具所需要的最少次数那么d[i][j] = min(d[i-1]

HDU2602 01背包 xingxing在努力

很经典的01背包, 假设f(i, j)是将i个物品放入容量为j的背包, 那么可得到如下递推式f(i, j) = max(f(i-1, j) , f(i-1, j-c[i])+v[i]))....实现的话有两种方式, 一种是直接用二维数组实现, 另外一种是滚动数组, 不过要注意的是, 如果题意是让这些物品恰好装满背包,那么f(0, 0)为0其他为无穷大, 如果没必要恰好装满那就全部初始化为0: 代码如下: #include <cstdio> #include <cstring> #i

POJ2184 01背包变形 xingxing在努力

这道题乍一看就有了思路,大体就是定了其中一个值然后再求另外一个值的最大值, 然而代码实现好坑, 题意是奶牛有两个属性 Ai和Bi, 让你求Ai和Bi和的最大值,注意Ai的和不能为负整数, Bi也一样..假设我们定了Ai我们来看下状态方程:f[i][j] = max(f[i-1][j], f[i-1][j-A[i]]+B[i]).当A[i]为正的时候就是我们经常遇到的01背包,使用滚动数组倒着排一遍, 然而当A[i]为负的时候我们就应该从小推到大,这样才对..代码如下: #include <cst

HDU2955 01背包变体 xingxing在努力

这道题的题意是小偷要去偷N家银行, 每家银行都有一个钱款数额Mi和被抓概率pi, 求小偷被抓的概率小于P的情况下所能偷到的钱数额的最大值(每家银行最多偷一次),由于每家银行最多偷一次, 所以这个题可以用01背包的思想来求解, 又因为小偷被抓会有很多种情况,并不好算,因此我们用他的反面小偷成功逃脱来算?这样题目就成了小偷在成功逃脱的概率大于1-P的情况下所能偷到的钱数最大值..记f[i][j]为小偷在前i家银行恰好偷了j块钱成功逃脱的 概率最大值, 那么f[i][j] = max(f[i-1][j

Uva624 01背包输出方案 xingxing在努力

题目是给你一个长度为N的磁带, 让你将t首歌放入磁带中, 输出歌曲总长度不超过N的情况下的方案. 代码如下: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int c[30]; int f[10000 + 100]; int vis[30][10000 + 10]; int n, m; int main() { while(scanf("%d%d&q

HDU5074 dp xingxing在努力

这道题就是给你一个序列a, 定义序列的最优美度为d[a[i]][a[i+1]], 现在让sigma(d[a[i]][a[i+1]]) i=1 - n-1最大,当a[i]<0是序列这个位置可以随便选, 否则不能随便选, 则sigma(d[a[i]][a[i+1]]) i=1 - n-1最大是多少?这道题乍一看是搜索, 然而看一下数据范围, 感觉搜索胜任不了, 于是果断想了一种dp的做法,定义dp[i][j]为第i个位置为j时的最大值, 那么答案就可以推出来, 具体见代码: /***********

HDU5592 排队问题 xingxing在努力

题意就不多说了, 题可以转化为排队问题, 我们可以使用树状数组来维护,代码如下: #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn = 50010; int n; int c[maxn]; int lowbit(int x) { return x&(-x); } int sum(int i) { int s = 0; whil

POJ1275 很好地差分约束系统 xingxing在努力

还是花费了几天A这道题的, 蛮好的一道题, 题意是有一家咖啡店在二十四小时内每个小时段都需要一定数目的服务员来提供服务, 有n个应聘者来来这家店(一旦应聘者从第i小时开始工作那么他就要连续的工作八个小时), 现在给定应聘者的数量问你最少需要多少个服务员能满足这家店的需求. 假设r[i]是这家店第i到第i+1小时所需要的服务员的最小数目,t[i]表示第i时刻来应聘的人数, s[i]表示前i个小时段内店铺招的总人数那么就可以得到下面的约束公式: 0=<s[i] - s[i-1]<=t[i]