(复习)poj 1742 coins 多重背包可达性问题

来源:互联网 发布:淘宝网冬季女式皮鞋 编辑:程序博客网 时间:2024/05/14 03:56

Coins
Time Limit: 3000MS Memory Limit: 30000KTotal Submissions: 28958 Accepted: 9828

Description

People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch. 
You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins. 

Input

The input contains several test cases. The first line of each test case contains two integers n(1<=n<=100),m(m<=100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000). The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.

Sample Input

3 101 2 4 2 1 12 51 4 2 10 0

Sample Output

84

Source

LouTiancheng@POJ


题目大意:

有n种面额的硬币,分别为a[i],每种硬币一共有c[i]个。问可以构造出多少不同的价格。


总结&反思:

这道题做得实在是没有思路,

总的来说是————

没有真正理解好多重背包问题一维dp的多态叠加性质,而这是因为平时没有主动使用一维dp造成的。

并且,老是被自己的固有思维限制住,总是想用“二进制优化”以及“队列优化”


这道题有两个闪光点,第一个就是多态叠加的应用,第二个就是下面代码中num数组的使用

而多态叠加这个性质或者说真正理解一维dp正是这道题的突破关键点,第一个问题解决了,相信我肯定可以解决出第二个问题。


解题思路:

(1)对于每一种商品(硬币),从1到m便利一遍所有价格,如果j-a[i]是可构造的,那么jj就是可构造的,所以我们用dp来表示是否可构造。

(2)因为每种商品有多个,j-a[i]可以是之前不同商品的叠加,也可以是当前商品若干个叠加的结果,对于前者没有限制。而对于后者,使用当前商品的

个数必须小于当前商品的最大个数(且这个数值只在当前的i的时候使用,过时就无用了),那么我们就可以用一个数组num来记录当前这个价格是当前商品的几次叠加

每进入一个新的i时就归零一次。




下面是ac代码:

#include <iostream>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <math.h>#include <memory.h>#include <string>#include <vector>#include <list>#include <map>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <numeric>#include <functional>#define maxn 1000005using namespace std;bool dp[100002];int num[100002];int a[102];int c[102];int n,m;int main(){    while(scanf("%d%d",&n,&m)!=EOF){        if(!n&&!m) return 0;        int res=0;        memset(dp,false,sizeof(dp));        memset(num,0,sizeof(num));        for(int i=1;i<=n;i+=1){            scanf("%d",&a[i]);        }        for(int i=1;i<=n;i+=1){            scanf("%d",&c[i]);        }        dp[0]=true;        for(int i=1;i<=n;i+=1){            memset(num,0,sizeof(num));            for(int j=a[i];j<=m;j+=1){                if(dp[j-a[i]]&&!dp[j]&&num[j-a[i]]<c[i]){                    dp[j]=true;                    res+=1;                    num[j]=num[j-a[i]]+1;                }            }        }        printf("%d\n",res);    }    return 0;}







0 0
原创粉丝点击