AtCoder Beginner Contest 286—D—Money in Hand

题目链接:

题意:
我有N种硬币,每种硬币有 Bi (1=<i<=N)个,每种硬币的价值为 A[i];

思路:

状态表示:f[i][j]:从前i种硬币当中选,且所选硬币的价值恰好为 j 的方案。
属性:存在性,价值为 j 的方案能否凑出来;
所以 f[i][j] 的取值就变成了 0 或者 1,分别表示不能凑出来,或者能够凑出来!

状态转移:
f [i] [j]:<— f[i-1][j] ,从前i-1种硬币当中选,且不选第i种硬币,价值为 j 的方案!
f [i][j]:<—f[i-1][j-k*a[i]],从前i种硬币当中选,并且选第i种硬币,且第i种硬币选k个,价值恰好为j的所有方案!

代码:

暴力:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int N = 1e4 + 10;
int a[N], b[N];		//硬币的价值 ! 
int f[N];		//本来是2维的! 

int main()
{
	int n, x;
	cin >> n >> x;	//n种物品,背包体积为x元
	
	for (int i=1; i <= n; i ++)
		cin >> a[i]	>> b[i];//输入每种物品的价值和数量 
	
	//恰好类型的初始化:
	f[0] = 1;	//表示从前i种硬币中选,价值为0的选法:=1表示存在,即什么都不选! 
	
	for (int i=1; i <= n; i ++)	//考虑前i种物品!
	{
		for (int j=x; j >= 0; j --)
		{
			for (int k=1; k <= b[i]; k ++)	//枚举每种物品选多少个合适 
				if (k*a[i] <= j)
					f[j] = f[j] | f[j-k*a[i]];
		}
	}
	
	if (f[x]) puts("Yes");
	else puts("No");
	 
	return 0;
}

二进制优化:

单调队列优化:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值