POJ 1384 Piggy-Bank(完全背包)

来源:互联网 发布:软件测试师考试 编辑:程序博客网 时间:2024/06/05 17:49

POJ 1384 Piggy-Bank(完全背包)

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

题意:

       现在有n种硬币,每种硬币有特定的重量cost[i] 克和它对应的价值val[i]. 每种硬币可以无限使用. 已知现在一个储蓄罐中所有硬币的总重量正好为m克, 问你这个储蓄罐中最少有多少价值的硬币? 如果不可能存在m克的情况, 那么就输出” This is impossible.”.

分析:

       由于每种硬币可以无限使用, 所以是明显的完全背包问题.

       本题的限制条件: 硬币总重量正好等于m.

       本题的目标条件: 硬币总价值尽量小.

       令dp[i][j]==x 表示只用前i种货币, 且当总重量达到j克时的最小价值和为x.

       初始化: 所有dp都为INF(无穷大), 且dp[0]==0. (因为本题的目标是价值最小,所以初始化为无穷大.如果要让目标最大, 那么应该初始化为-1.)

       状态转移: dp[i][j] = min( dp[i-1][j] , dp[i][j-cost[i]]+val[i])

       上面方程前者表示第i种硬币一个都不选, 后者表示至少选1个第i种硬币.

       最终所求为dp[n][m]. (如果dp[n][m]==INF,说明m克是一个不可达的状态)

       本题程序用的滚动数组, 所以dp只有[j]这一维.

AC代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=10000+5;#define INF 1e9int n;//货币种数int m;//最大重量int dp[maxn];int cost[maxn];//每种货币重量int val[maxn]; //每种货币价值int main(){    int T; scanf("%d",&T);    while(T--)    {        //读入数据        int m1,m2;        scanf("%d%d%d",&m1,&m2,&n);        m=m2-m1;        for(int i=1;i<=n;i++)            scanf("%d%d",&val[i],&cost[i]);        //初始化        for(int i=0;i<=m;i++) dp[i]=INF;        dp[0]=0;        //递推过程        for(int i=1;i<=n;i++)        {            for(int j=cost[i];j<=m;j++)                dp[j] = min(dp[j], dp[j-cost[i]]+val[i]);        }        //输出结果        if(dp[m]==INF) printf("This is impossible.\n");        else printf("The minimum amount of money in the piggy-bank is %d.\n",dp[m]);    }    return 0;}

0 0
原创粉丝点击