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
思路:
- 和多重揹包的意思差不多
- 對於每個硬幣沒有價值之分,只有可行與不可行
難點:
- 多重揹包在用模板的時候不需要Value一項,然後需要用|=來優化多重揹包的max()函數,最後是dp數組需要設置爲bool類型,代表 元時是不是可行
- 如果不優化就會超時
題解:
#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;
}