0-1背包(OJ0161)新解

#include<iostream>
#include<cstdio>
using namespace std;
int v[21],w[21];
int main()
{
	int n,c;
	scanf("%d%d",&n,&c);
	for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&w[i]);//输入
	int m=1<<n;//2^n
	int ans=0;
	for(int i=0;i<m;i++){//枚举所有情况
		int x=0,y=0;
		for(int j=1;j<=n;j++){
			bool flag=(i>>(j-1))%2;//取i的二进制第j位
			if(flag) x+=v[j],y+=w[j];//x,y分别表示当前体积、价值
			if(x>c){
				y-=w[j];//
				break;
			}
		}
		if(x<=c) ans=max(ans,y);//取最大价值
	}
	printf("%d",ans);//输出
	return 0;
}

数据范围:输入的数据均不超过20,经典的搜索

众所周知,01背包的正解是DP。但是本题输入的数据不超过20,是否可以暴力求解呢?

回归01背包的本质,每件物品只有0(不取)和1(取)和两种可能。直接暴力枚举的时间复杂度是O(2^n),意味着1s以内可以得到结果。

为了提升运算速度,采用二进制。二进制下i的第j位为0表示不取第j件物品,否则表示取第j件物品。

32ms,440KB,AC。此算法空间复杂度较低。

原文地址:https://www.cnblogs.com/dong-ji-yuan/p/9799349.html