POJ 1742 Coins 多重揹包

POJ1742

Coins

Time Limit: 3000MS   Memory Limit: 30000K
Total Submissions: 47417   Accepted: 15982

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 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0

Sample Output

8
4

思路:

  1. 和多重揹包的意思差不多
  2. 對於每個硬幣沒有價值之分,只有可行與不可行

難點:

  1. 多重揹包在用模板的時候不需要Value一項,然後需要用|=來優化多重揹包的max()函數,最後是dp數組需要設置爲bool類型,代表 i 元時是不是可行
  2. 如果不優化就會超時

題解:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <iterator>
#define INF 0x3f3f3f3f
#define maxn 100007
// #define LOCAL
using namespace std;
typedef long long ll;


bool dp[maxn];
int value[maxn],weight[maxn],number[maxn];//分別存的是物品的價值,每一個的重量以及數量
int bag;	// 揹包大小

void ZeroOnePack(int weight)//01揹包
{
    for(int i = bag; i>=weight; i--)
    {
        dp[i] |= dp[i-weight];
    }
}
void CompletePack(int weight)//完全揹包
{
    for(int i = weight; i<=bag; i++)
    {
        dp[i] |= dp[i-weight];
    }
}
 
void MultiplePack(int weight, int number)//多重揹包
{
    if(bag <= number * weight)//如果總容量比這個物品的容量要小,那麼這個物品可以直到取完,相當於完全揹包
    {
        CompletePack(weight);
        return;
    }
    else//否則就將多重揹包轉化爲01揹包
    {
        int k = 1;
        while(k < number)
        {
            ZeroOnePack(k * weight);
            number -= k;
            k <<= 1;	//這裏採用二進制思想
        }
        if (number > 0)
        {
        	ZeroOnePack(number*weight);
        }
        return;
    }
}

int main()
{
#ifdef LOCAL
    freopen("data.in", "r", stdin);
    freopen("data.out", "w", stdout);
#endif


   int n;
   while(scanf("%d%d", &n, &bag)){
   		if (n==0 && bag==0)
   		{
   			break;
   		}
   		memset(dp, 0, sizeof(dp));
   		memset(value, 0, sizeof(value));
   		memset(weight, 0, sizeof(weight));
   		memset(number, 0, sizeof(number));
   		for (int i = 1; i <= n; ++i)
   		{
   			scanf("%d", &weight[i]);
   		}
   		for (int i = 1; i <= n; ++i)
   		{
   			scanf("%d", &number[i]);
   		}
   		dp[0] = 1;
   		for (int i = 1; i <= n; ++i)
   		{
   			MultiplePack(weight[i], number[i]);	// value是0
   		}
   		
   		int sum = 0;
   		for (int i = 1; i <= bag; ++i)
   		{
   			if (dp[i])
   			{
   				sum ++;
   			}
   		}
   		cout << sum << endl;
   }


#ifdef LOCAL
    fclose(stdin);
    fclose(stdout);
#endif

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章