poj 3260 最少硬币(01+多重+完全背包)

http://www.cnblogs.com/ACMan/archive/2012/08/14/2637437.html

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <cctype>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <sstream>
using namespace std;

#define mem(a,b) memset(a,b,sizeof(a))
#define pf printf
#define sf scanf
#define spf sprintf
#define pb push_back
#define debug printf("!\n")
#define MAXN 1010
#define MAX(a,b) a>b?a:b
#define blank pf("\n")
#define LL long long
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pqueue priority_queue
#define INF 0x3f3f3f3f

int n,T;

const int mx = 30000;

int dp[30000],f[30000],w[30000],c[30000];

void zobag(int value,int weight)
{
    for(int v = mx;v>=weight;v--)
    {
        dp[v] = min(dp[v],dp[v-weight]+value);
    }
}

void cmbag(int value,int weight)
{
    for(int v = weight;v<=mx;v++)
    {
        dp[v] = min(dp[v],dp[v-weight]+value);
    }
}

void fcmbag(int value,int weight)
{
    for(int v = weight;v<=mx;v++)
    {
        f[v] = min(f[v],f[v-weight]+value);
        //pf("v%d f%d\n",v,f[v]);
    }
}

void mubag(int weight,int amount)
{
    if(weight*amount >= mx)
    {
        cmbag(1,weight);
        return;
    }
    int k = 1;
    while(k < amount)
    {
        //pf("amt%d\n",amount);
        //pf("k%d\n",k);
        zobag(k,k*weight);
        amount-=k;
        k*=2;
    }
    zobag(amount,amount*weight);
}

int main()
{
    int i,j;
    while(~sf("%d%d",&n,&T))
    {
        mem(dp,INF);
        mem(f,INF);
        dp[0]=0;
        for(i=0;i<n;i++)
        {
            sf("%d",&w[i]);
        }
        for(i=0;i<n;i++)
        {
            sf("%d",&c[i]);
        }
        for(i=0;i<n;i++)
        {
            mubag(w[i],c[i]);
        }
        f[0]=0;
        for(i=0;i<n;i++)
        {
            fcmbag(1,w[i]);
        }
        int ans = INF;
        for(i=0;i<mx-T;i++)
        {
            ans = min(ans,dp[i+T]+f[i]);
        }
        if(ans == INF) ans = -1;
        pf("%d\n",ans);
    }
    return 0;
}
时间: 2024-08-10 00:06:49

poj 3260 最少硬币(01+多重+完全背包)的相关文章

POJ 3260 The Fewest Coins 最少硬币个数(完全背包+多重背包,混合型)

题意:FJ身上有各种硬币,但是要买m元的东西,想用最少的硬币个数去买,且找回的硬币数量也是最少(老板会按照最少的量自动找钱),即掏出的硬币和收到的硬币个数最少. 思路:老板会自动找钱,且按最少的找,硬币数量也不限,那么可以用完全背包得出组成每个数目的硬币最少数量.而FJ带的钱是有限的,那么必须用多重背包,因为掏出的钱必须大于m,那么我们所要的是大于等于m钱的硬币个数,但是FJ带的钱可能很多,超过m的很多倍都可能,那么肯定要有个背包容量上限,网上说的根据抽屉原理是m+max*max,这里的max指

POJ 3260 The Fewest Coins(多重背包+全然背包)

http://poj.org/problem?id=3260 题意: John要去买价值为m的商品. 如今的货币系统有n种货币,相应面值为val[1],val[2]-val[n]. 然后他身上每种货币有num[i]个. John必须付给售货员>=m的金钱, 然后售货员会用最少的货币数量找钱给John. 问你John的交易过程中, 他给售货员的货币数目+售货员找钱给他的货币数目 的和最小值是多少? 分析: 本题与POJ 1252类型: http://blog.csdn.net/u013480600

poj 3260 The Fewest Coins 多重背包+完全背包

题目链接:http://poj.org/problem?id=3260 给店家的钱是多重背包 dp[] 店家的找钱是完全背包 dp2[] 然后最后 其中i表示多给了多少钱 也就是需要找回多少钱 int ans = INF; ans = min(ans, dp[m+i] + dp2[i]); 是一个比较简单的思路 神坑题 看到每种货币的面值不大于120 我就觉得找钱一定不会超过119块钱结果wa到死 后来才发现不是的啊 之所以我有这种思维定式是因为现实生活中有1块钱这种货币单位 考虑一种极限的情况

混合背包(多重背包+完全背包)—— POJ 3260

对应POJ题目:点击打开链接 The Fewest Coins Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5450   Accepted: 1653 Description Farmer John has gone to town to buy some farm supplies. Being a very efficient man, he always pays for his goods in such a

POJ 2392 Space Elevator(贪心+多重背包)

POJ 2392 Space Elevator(贪心+多重背包) http://poj.org/problem?id=2392 题意: 题意:给定n种积木,每种积木都有一个高度h[i],一个数量num[i],还有一个限制条件,这个积木所在的位置不能高于limit[i],问能叠起的最大高度? 分析: 本题是一道多重背包问题, 不过每个物品的选择不仅仅要受该种物品的数量num[i]限制, 且该物品还受到limit[i]的限制. 这里有一个贪心的结论: 我们每次背包选取物品时都应该优先放置当前limi

POJ 3628 Bookshelf 2 (01背包)

Bookshelf 2 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7496   Accepted: 3451 Description Farmer John recently bought another bookshelf for the cow library, but the shelf is getting filled up quite quickly, and now the only available

Poj 1112 Rebuilding Roads(树形DP+背包)

题意:给你由N个点构成一颗树,问要孤立出一个有P个节点的子树最少需要删除多少条边.N的范围最大为150 N的范围不大,很容易想到在树上面做背包.把每个节点都看成一个背包,然后把每个儿子节点都看成是一组物品.为什么是一组呢,那是因为假设以儿子为根的节点的子树有S个节点,那么就有S+1种情况,要么将这整棵子树舍弃,要么从这个子树中取1-S个节点. 设f[i][j]为以i为根节点的子树,孤立出以i为根节点,一共含有j个节点的子树最少需要删除的边数(不包括删除i和他父亲的连接的那条边(假设i不是根节点)

算法笔记——硬币找零之最少硬币数

题目来源:NYOJ995 问题描述: 在现实生活中,我们经常遇到硬币找零的问题,例如,在发工资时,财务人员就需要计算最少的找零硬币数,以便他们能从银行拿回最少的硬币数,并保证能用这些硬币发工资. 我们应该注意到,人民币的硬币系统是 100,50,20,10,5,2,1,0.5,0.2,0.1,0.05, 0.02,0.01 元,采用这些硬币我们可以对任何一个工资数用贪心算法求出其最少硬币数. 但不幸的是: 我们可能没有这样一种好的硬币系统, 因此用贪心算法不能求出最少的硬币数,甚至有些金钱总数还

POJ 3132 Sum of Different Primes DP背包

http://poj.org/problem?id=3132 题意: 给定n和k,问用恰好k个不同的质数来表示n的方案数. 分析: n和k都很小.反正就是个背包,选k个物品恰好填满n即可. 1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 5 bool dp[1200][15]; 6 int ct[1200][15]; 7 int p[1200]; 8 bool a[1200]; 9 int n, k,