09-06 HDU_Steps4.3 DFS剪枝 HDU1010 HDU1016 HDU1426 HDU1455 HDU2510 HDU2553 HDU3290 HDU2616

HDU_Steps 4.3 DFS剪枝


4.3.1 HDU1010 Tempter of the Bone

具体剪枝在这篇文章有写http://blog.csdn.net/swm8023/article/details/6731109


4.3.2 HDU1016 Prime Ring Problem

直接搜就可以了,先打好40以内的素数表


4.3.3 HDU1426 Sudoku Killer

也是赤果果的搜索+回溯,对每个未填的点枚举1~9,然后判断所在列,所在行,以及所在九宫格是否有重复的没有任何剪枝170MS.


4.3.4 HDU1455 Sticks

比较经典的一道剪枝

首先要枚举长度,从最长一根的长度开始枚举,并且从大到小放置树枝

另外注意的就是会有很多长度相同的树枝,当然,对于这样的树枝,如果一根不满足条件,其它的也不会满足了

当然,这道题的剪枝还有不少,网上有大牛给出了各种剪枝,这里的两个剪枝对于这道题已经足够了~

#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
int st[70],n,sum,len;
bool use[70]; 
bool dfs(int cnt,int rlen,int sts){//总剩余长度,该根剩下的长度,剩下的根数 
	if(rlen==0){
		sts--;
		if(sts==0)return true;
		//找出当前未用的最长根作为开始 
		for(cnt=n;use[cnt];cnt--);
		use[cnt]=true;
		if(dfs(cnt-1,len-st[cnt],sts))return true;
		use[cnt]=false;
		sts++;
	}else{
		for(int i=cnt;i>=1;i--){
			if(i<n&&st[i]==st[i+1]&&!use[i+1])continue;//同样长度的不行,这根同样不行 
			
			if(!use[i]&&rlen>=st[i]){
				use[i]=true;
				if(dfs(i-1,rlen-st[i],sts))return true;
				use[i]=false;	
			}
		
		}
	}
	return false;
}
int main(){
	while(scanf("%d",&n),n){
		sum=0;
		for(int i=1;i<=n;i++){
			scanf("%d",&st[i]);
			sum+=st[i];	
		}
		sort(st+1,st+n+1);
		
		for(len=st[n];len<=sum;len++){
			if(sum%len!=0)continue;
			memset(use,false,sizeof use);
			if(dfs(n,len,sum/len)){
				printf("%d\n",len);
				break;	
			}	
		}
		
	}
	return 0;	
} 

4.3.5 HDU2510 符号三角形

写了个位运算搜索,果断超时啊..一看范围只有24,可耻的打表过了..

感觉这题可能是DP方法吧..搜索肯定是挂了..先放着,有时间再研究.


4.3.6 HDU2553 N皇后问题

看到这题就想到了67大牛的那篇文章,牛啊..短小精悍的程序

用row,ld,rd分别表示列上,左对角线上,右对角线上不能放的位置,full表示全部放满的状态..用树状数组的lowbit操作取出pos中的每一个1,也就是每一个能放的位置,然后继续搜索,左对角线和右对角线向下一行搜索时要分别右移或者左移一位

#include <cstdio>
using namespace std;
int n,res,full,ans[11];
void dfs(int row,int ld,int rd){
	int pos,p;
	if(row!=full){
		pos=full&~(row|ld|rd);
		while(pos){
			p=pos&-pos;
			pos-=p;
			dfs(row|p,(ld|p)<<1,(rd|p)>>1);	
		}
	}else res++;	
}

int main(){
	for(int i=1;i<=10;i++){
		res=0;
		full=(1<<i)-1;
		dfs(0,0,0);
		ans[i]=res;			
	}
	while(scanf("%d",&n),n){
		printf("%d\n",ans[n]); 
	}
	return 0;	
} 


4.3.7 HDU3290 The magic apple tree

晕,看题目看了好久才看懂,一棵树中,第一天只有子节点开花(不记得是不是开花,反正是这个意思),数量等于节点标记,一个父节点只有当它的所有子节点都开花时才会开花,数量等于子节点的(K+1)/2

这题不能说是搜索吧,更有点像树形DP..

树是连续读入的,所有节点存在v中,num表示子节点个数,注意没有说明根节点!!!要先找到根,因为这个一直TLE,郁闷

#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
int first[20001],num[20001],v[20001],vs,n,in[20001];
char c;
int getv(int p){
	if(num[p]==0)return p;
	nth_element(v+first[p],v+first[p]+(num[p]+1)/2-1,v+first[p]+num[p]);
	return v[first[p]+(num[p]+1)/2-1]; 
}
void dfs(int p){
	for(int i=0;i<num[p];i++){
		int t=v[first[p]+i];
		if(num[t]!=0)dfs(t);
		v[first[p]+i]= getv(t);//跟新当前节点值 
	}
}
inline void scan(int &x){
	while(c=getchar(),c<'0'||c>'9');
	x=c-'0';
	while(c=getchar(),c>='0'&&c<='9')x=x*10+c-'0';	
}
int main(){
	while(scanf("%d",&n)!=EOF){
		first[1]=1;
		vs=1;
		for(int i=1;i<=n;i++)in[i]=0;
		
		for(int i=1;i<=n;i++){
			scan(num[i]);//child个数,也是child所占连续空间 
			for(int j=0;j<num[i];j++){
				scan(v[vs]);
				in[v[vs]]++;
				vs++;
			}
			first[i+1]=first[i]+num[i];//标记下一个节点child的存储开始位置 
		}
		
		first[0]=0,num[0]=1;
		for(int i=1;i<=n;i++){if(in[i]==0){v[0]=i;break;}}
		dfs(0);	 
		printf("%d\n",v[0]);
	}
	return 0;	
}

4.3.8  HDU2616 Kill the monster
简单的深搜+回溯
#include <cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
int n,m,bella[12],bellm[12],a[12],use[12],res;
void dfs(int p){
	if(p==n+1){
		int nowm=m;
		for(int i=1;i<=n;i++){
			if(nowm<=bellm[a[i]])nowm-=2*bella[a[i]];
			else nowm-=bella[a[i]];
			if(nowm<=0){
				res=min(res,i);
			}
		}
	}
	for(int i=1;i<=n;i++){
		if(!use[i]){
			use[i]=1;
			a[p]=i;
			dfs(p+1);
			use[i]=0;	
		}	
	}
}
int main(){
	while(scanf("%d%d",&n,&m)!=EOF){
		for(int i=1;i<=n;i++)scanf("%d%d",&bella[i],&bellm[i]);
		memset(use,0,sizeof use);
		res=20;
		dfs(1);
		if(res!=20)printf("%d\n",res);
		else printf("-1\n");
	}
	return 0;	
}



你可能感兴趣的:(09-06 HDU_Steps4.3 DFS剪枝 HDU1010 HDU1016 HDU1426 HDU1455 HDU2510 HDU2553 HDU3290 HDU2616)