POJ 1742 Coins

Coins
Time Limit: 3000MS Memory Limit: 30000K
Total Submissions: 21637 Accepted: 7358

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

Source


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int N, V;
int v[110], n[110]; 
int f[100010];

int main(){
	int i, j, k;
	while(scanf("%d%d", &N, &V) != EOF, N != 0 || V != 0){
		for (i = 0; i < N; i++){
			scanf("%d", &v[i]);
		}
		for (i = 0; i < N; i++){
			scanf("%d", &n[i]);
		}
		memset(f, 0xff, sizeof(int) * (V + 1));
		f[0] = 0;
		for (i = 0; i < N; i++){
			for (j = 0; j <= V; j++){
				if (f[j] >= 0){
					f[j] = 0;
				}else if (j >= v[i] && f[j - v[i]] >= 0 && f[j - v[i]] < n[i]){
					f[j] = f[j - v[i]] + 1;
				}
			}
		}
		k = 0;
		for (i = V; i >= 1; i--)
			if (f[i] >= 0) k++;
		printf("%d\n", k);
	}
	return 0;
}
/*
f[i][j]表示前i种钱币,组成面值j,使用第i种钱币最少的数量
明明只是求j的可达性,却通过这么一个巧妙的状态,
使得复杂度减至O(N*V),N是组数
带二进制优化的分组背包是O(sum(log(num[i]))*V)
对于这状态的另一种理解
普通背包
j = 0时
遍历 v[i], 2 * v[i], 3 * v[i],..., n[i] * v[i]
j = 1时
遍历 1 + v[i], 2 + 2 * v[i]...
j = v[i]时
遍历 2 * v[i], 3 * v[i]...
发现和上面重了,这块重复的搜索很浪费啊,怎么解决呢
看到,如果n[i]有无穷大,那么j>=v[i]的会完全与j=0...v[i]-1的重复
但n[i]是有限的,只循环j=0...v[i]-1,有些数量不够,
需要借助之前物品的,就遍历不到了
一种想法是,尽量节省地使用物品i,记录i在凑成j时最少使用的数量
如果之前物品能够凑出j,那就不用使用物品i了
这样节省地遍历下j=0...v[i]-1,算起来时间复杂度还是O(N*V)

不过奇怪了,开始写的是
j = v[i] to V
if (...)中不带j >= v[i]的判断,结果RE了
其实应该WA,因为j=0...v[i]-1的f[j]没有清0...
改完后就AC了。奇怪为啥是RE...
*/


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值