1. 程式人生 > >利用位運算來求組合問題:

利用位運算來求組合問題:

題目如下:

連結:https://ac.nowcoder.com/acm/contest/303/D
來源:牛客網
 

星際爭霸(StarCraft)單人戰役模式中有很多供人遊玩的任務關卡。

 

tokitsukaze新開始了一關單人戰役模式下的任務。在這場戰役中,你要作為指揮官指揮克魯普星區的艾倫人類(Terran)來防禦人類的敵人——邪惡異蟲(Zerg)的襲擊。

 

這一次,作為指揮官,你的任務目標是儘可能多的保全人類方所擁有的7個基地。你在這次任務中擁有n個人口單位的兵力。為了防禦異蟲的攻擊,每個基地都有一個能夠抵擋異蟲攻擊的最小兵力需求L[i],同時每個基地因為有固定的人口上限,分配給該基地的兵力也不得大於上限R[i]。

 

你需要在任務一開始就為這7個基地做好兵力分配,每個兵都應該分配給一個基地,即不應該有空閒兵力。如果任何一個基地被異蟲攻破(分配的兵力大於0,且小於最小兵力需求,導致兵力白白葬送犧牲),或者某個基地的人口超過了人口上限,兵力大於R[i],任務都會直接失敗。

 

為了避免任務失敗,tokitsukaze決定從一開始就放棄一些基地(即不對這些基地派出兵力)。

 

請問保證任務成功的條件下,tokitsukaze最多留下多少個基地?特別的,如果任務失敗這種情況下請輸出"0",不含引號。

 

由於tokitsukaze的星際操作十分流弊,你可以認為如果能夠至少能夠保留一個基地,任務就一定能夠成功。

輸入描述:

第一行輸入一個T(T≤50000),表示T組資料。

對於每組資料:
輸入一個正整數n(1≤n≤10^9)表示需要分配的兵力總人口。
接下來7行,每行兩個正整數L,R(1≤L≤R≤10^9),分別表示該基地夠抵擋異蟲攻擊的最小兵力需求與該基地的人口上限。

輸出描述:

對於每組資料,輸出tokitsukaze最多能夠留下幾個基地,每組資料佔一行。

這道題沒有做出來,想到可以暴力,但是不知道如何暴力,這就凸顯自己做的題太少;看了別人的程式碼發現,位運算原來有如此強大的功能;有位運算的每個位置所在是否為1可以把所有情況都表示出來,然後找到其中的最優解,也可以使用dfs來做對於每一個位置的數加或者不加,最後輸出最優解;

位運算程式碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
//#define e exp(1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
#define INF 0x3f3f3f3f
#define inf -2100000000
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 100 + 10;
const double EPS = 1e-10;
const ll p = 1e7+9;
const ll mod = 1e9+7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
    int ret=0,f=0;char ch=getchar();
    while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return f?-ret:ret;
}
int t;
struct node{
	int x,y;
}a[10];

int main(){
	ios::sync_with_stdio(false);
	cin >> t;
	
	int n;
	while(t--){
		cin >> n;
		int q = (1 << 7);
		for(int i = 0; i < 7; i++){
			cin >> a[i].x >> a[i].y;
		}
		int minn = 0;
		int maxnn = 0;
		int ans = 0;
		int sum = 0;
		for(int i = 0; i < q; i++){
			minn = 0;
			maxnn = 0;
			ans = 0;
			for(int j = 0; j < 7; j++){
				if(i&(1<<j)){
					minn += a[j].x;
					maxnn += a[j].y;
					ans ++;	
				}
				if(minn <= n && maxnn >= n){
					sum = max(ans,sum);
				}
			}
		}
		cout << sum << endl;
	}
	return 0;
}

dfs程式碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pi acos(-1)
#define e exp(1)
#define For(i, a, b) for(int (i) = (a); (i) <= (b); (i) ++)
#define Bor(i, a, b) for(int (i) = (b); (i) >= (a); (i) --)
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define eps 1e-7
#define INF 0x3f3f3f3f
#define inf -2100000000
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 100 + 10;
const double EPS = 1e-10;
const ll p = 1e7+9;
const ll mod = 1e9+7;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
inline int read(){
    int ret=0,f=0;char ch=getchar();
    while(ch>'9'||ch<'0') f^=ch=='-',ch=getchar();
    while(ch<='9'&&ch>='0') ret=ret*10+ch-'0',ch=getchar();
    return f?-ret:ret;
}
int t;
struct node{
	int x, y;
}a[10];
int sum = 0;
int n;
void dfs(int l, int r, int ans, int m){
	if(ans == 7){
		if(l <= n && r >= n){
			sum = max(sum, m);
		}
		return ;
	}else{
		dfs(l+a[ans].x, r + a[ans].y, ans+1, m+1);
		dfs(l,r,ans+1, m);
	}
	return ;
}
int main(){
	ios::sync_with_stdio(false);
	cin >> t;
	while(t --){
		cin >> n;
		for(int i = 0; i < 7; i++){
			cin >> a[i].x >> a[i].y;
		}
		sum = 0;
		dfs(0,0,0,0);
		cout << sum << endl;
	}
	return 0;
}