hdu3185 Dead Or Alive

Dead Or Alive

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 69    Accepted Submission(s): 6


Problem Description
Only several people survive after Doomsday, and a small number of cities have not been destroyed. yifenfei wants to arrange these people to live on the available cities.
Now all the people follow yifenfei to pass the cities.
But there are some restrictions on the cities. Some people will die when pass some cities and every city has a population limitation. If people can’t find a city to live after passing all cities they will be dead! So the order of passing the cities is important.
 

Input
The first line an integer T (1<=T<=100) which means the number of test cases.
Each case starts with two integers n and m, which means the number of people and the number of cities. (1<= n <= 31, 1 <= m <= 10)
Second line has m integers, the ith integer Ci means ith city’s population limitation. The cities are ordered from 0 to m-1. (1 <= Ci <= 6)
Then n lines follow. Each line starts with an integer k which means the number of cities this people will die when passing it. Then k integers follow.
 

Output
The maximum number of people can survive!
 

Sample Input
 
  
23 33 3 21 102 1 23 32 1 22 0 12 0 21 2
 
Sample Output
 
  
32
 

Source
 

Recommend

lcy   |   We have carefully selected several similar problems for you:   3190  3187  3184  3186  3188 


题解:不知为什么我之前过的人只有四个(有一个提交了2次),而且还是7年以前的。

这题我的算法可能不是正解,跑了7700多毫秒,其余4个人最多只跑了200多毫秒。

我们先枚举所有城市的顺序(用搜索搜出来),这有!m种。先用一个2进制记录下每个城市会死哪些人(用01表示记录即可),记为g[i],在搜索时我们用个2进制记录哪些城市一定要放在这个城市前面(如果经过会死亡的啊),0表示一定要放在前面,1表示不一定。

然后转移就是 now=la&(~g[i])  (2进制操作)  //la为上一个位置的放置要求,now为这个位置的放置要求。

最后取最小值即可


代码(前面讲的云里雾里的):

#include<bits/stdc++.h>
using namespace std;
int ans,n,m,gg[50],a[50],b[50],c[50];
long long g[50];
void dfs(int x,long long la,int k,int k1,int sum){
	long long now;
	int t1,kk;
	if(x>m){
		if(m-sum-k>0)k+=m-sum-k;
		ans=min(ans,k);
		return;
	}	
	for(int i=0;i<m;i++)
	 if(gg[i]==0){
	 	gg[i]=1;b[x]=i;
		now=la&(~g[i]);
		c[x]=now;
	 	t1=k1-__builtin_popcount(now);
	 	//printf("%d %d\n",i,t1);
	 	//k1:now中1的个数
		//t1:now和la中1相差的个数 
	 	if(n-k1+t1-k>sum){
	 		kk=n-k1+t1-k-sum;
	 		dfs(x+1,now,k+kk,k1-t1,sum+a[i]);
		 }
		  else
	 	dfs(x+1,now,k,k1-t1,sum+a[i]);
	 	gg[i]=0;
	 }
}
int main(){
	int t1,i,j,k1,t;
	scanf("%d",&t1);
	while(t1--){
		memset(gg,0,sizeof(gg));
		memset(g,0,sizeof(g));
		scanf("%d%d",&n,&m);
		ans=n;
		for(i=0;i<m;i++){
			scanf("%d",&a[i]);
		} 
		for(i=1;i<=n;i++){
			scanf("%d",&k1);
			for(j=1;j<=k1;j++){
				scanf("%d",&t);
				g[t]|=1<<(i-1);
			}
		}
		dfs(1,(1<<n)-1,0,n,0);
		printf("%d\n",n-ans);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_41510496/article/details/80083802
今日推荐