信息学奥赛一本通 1267:01背包问题(暴力搜索、记忆化搜索)

题目链接:点击这里

信息学奥赛一本通 1267:01背包问题(暴力搜索、记忆化搜索)_第1张图片

01背包是dp的经典题目,记忆化搜索也是dp的实现方式之一。

特意找了个数据很水的题目,练习一下暴搜和记忆化搜索。

暴搜,时间复杂度为 O ( 2 n ) O(2^n) O(2n),可AC:

#include
#include
#include
using namespace std;
const int maxn = 100; 	//物品最大件数
int w[maxn];			//物品的重量
int c[maxn];			//物品的价值
int n, V;				//n为物品件数,V为背包容量 

//idx为物品编号、S为背包还剩多少容量
int search(int idx, int S)
{
	if(idx >= n)	return 0;					//已经没有物品了
	if(S < w[idx])	return search(idx+1, S);	//剩余容量不够放置当前物品 
	//选idx件获取它的价值和重量 或 不选idx件,取两者最大值 
	return max(search(idx+1,S-w[idx])+c[idx], search(idx+1,S));
}

int main() 
{
	scanf("%d%d", &V, &n);	
	for(int i = 0; i < n; i++)
		scanf("%d%d", &w[i], &c[i]);
	printf("%d\n", search(0, V));
	return 0;
}

暴力搜索存在大量重复,在其基础上加了个数组改为记忆化搜索,代码如下,可AC:

#include
#include
#include
using namespace std;
const int maxn = 100; 	//物品最大件数
int w[maxn];			//物品的重量
int c[maxn];			//物品的价值
int n, V;				//n为物品件数,V为背包容量
int f[50][300];

//idx为物品编号、S为背包还剩多少容量
int search(int idx, int S)
{
	if(idx >= n)	return 0;					//已经没有物品了
	if(S < w[idx])	return search(idx+1, S);	//剩余容量不够放置当前物品
	if(f[idx][S] >= 0)	return f[idx][S];
	//选idx件获取它的价值和重量 或 不选idx件,取两者最大值 
	f[idx][S] = max(search(idx+1,S-w[idx])+c[idx], search(idx+1,S));
	return f[idx][S];
}

int main() 
{
	for(int i = 0; i < 50; i++)
		for(int j = 0; j < 300; j++)
			f[i][j] = -1;
	scanf("%d%d", &V, &n);	
	for(int i = 0; i < n; i++)
		scanf("%d%d", &w[i], &c[i]);
	printf("%d\n", search(0, V));
	return 0;
}

你可能感兴趣的:(记忆化搜索)