np背包问题算法:折半枚举

Posted rstz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了np背包问题算法:折半枚举相关的知识,希望对你有一定的参考价值。

先看题吧

技术图片

我猜到多数人开始想的就是二进制暴力枚举,对吧,这题这样做可以因为只需要提交答案,完全可以本地暴力,1e9的数据。需要一分钟左右。

代码:

技术图片

这里我就不说着种方法了。

这题我们可以用,折半枚举。

优点:就是能够将时间复杂度降下来,将2^30 变为 2^15 + 2^15


解决这题仅仅用了不到1s的时间

代码也 相当于模板

  1 #include <algorithm>
  2 #include <map>
  3 #include <string>
  4 #include <iostream>
  5 using namespace std;
  6 typedef long long LL;
  7 
  8 constexpr size_t maxn = 100;
  9 
 10 LL A[100];
 11 map<LL, string> map1;
 12 int main(){
 13 	LL n;
 14 	LL value;
 15 	cin >> value >> n;
 16 	for(int i = 0; i < n; ++ i){
 17 		cin >> A[i];
 18 	}
 19 	for(int i = 0; i < (1 << (n/2)); ++ i){//将前半部分枚举 
 20 
 21 		string a = "";
 22 		LL sum = 0;
 23 		for(int j = 0; j < (n/2); ++ j){
 24 
 25 			if(i&(1<<j)){
 26 				sum += A[j];
 27 				a = a + ‘1‘;
 28 			}
 29 			else
 30 				a = a + ‘0‘;
 31 		}
 32 
 33 		map1[sum] = a;
 34 	}
 35 	for(int i = 0; i < (1 << (n - n/2)); ++ i){//枚举后半部分 
 36 
 37 		string a = "";
 38 		LL sum = 0;
 39 
 40 		for(int j = 0; j < (n - n/2); ++ j){
 41 
 42 			if(i&(1<<j)){
 43 				sum += A[j + n/2];
 44 
 45 				a = a + ‘1‘;
 46 			}
 47 			else
 48 				a = a + ‘0‘;
 49 		}
 50 
 51 		LL cd = value - sum;
 52 
 53 		auto iter = map1.find(cd);//查找 
 54 		if(iter != map1.end()){//找到退出 
 55 			cout << iter->second << a << endl;
 56 			return 0;
 57 		}
 58 	}
 59 	return 0;
 60 }






以上是关于np背包问题算法:折半枚举的主要内容,如果未能解决你的问题,请参考以下文章

[2017浙工大之江学院决赛 E] qwb和李主席(折半枚举,二分)

超大背包问题

算法刷题总结

算法刷题总结

算法刷题总结

C语言 背包问题 递归算法