noip 2015 斗地主 大爆搜

这道题有点坑,如果不是数据水的话,我应该根本活不过来。。。

不过有一个收获就是,看见大爆搜也不一定要害怕,万一数据水呢。。。。。。。。。

这道题我做了一下午,当然中间跟hyq下了一次象棋,本来能调的更快的,大概一个半小时之内应该可以。。。。,状态好的话考场上应该也能拿下!

首先我们明确暴力搜顺子,贪心出单牌,我们之所以可以贪心出单牌就是因为数据水,构造数据的话应该能卡掉,我在思考的时候就发现了一些可以卡掉的,数据水没办法。。。

先进行搜索顺子,然后从多到少的出单牌;

对于代码来说 cnt 是数量为1,2,3,4的 牌的数量。。。

而card是每一种牌的数量。。

#include
#include
#include
#include
#include 
#include
using namespace std;
int t,n;
int card[20],tmp[20],cnt[20],l;
int ans;
void init(){
	ans=n;
	memset(card,0,sizeof(card));
	memset(tmp,0,sizeof(tmp));
}
int sanpai(){
	memset(tmp,0,sizeof(tmp));
	int res=0;
	l=0;
	for(int i=1;i<=14;i++) tmp[i]=card[i],cnt[card[i]]++;
	
	for(int i=1;i<=14;i++){
		if(card[i]){
			l=i;
			break;
		}
		if(l==14) return 1;
	}
	
	if(cnt[4]&&cnt[2]>=2){		
		for(int i=l;i<=13;i++){
		    int vis=0;
			if(tmp[i]==4){
				for(int j=l;j<=14;j++){
					if(tmp[j]!=2||vis) continue;
					for(int k=l;k<=14;k++){
						if(tmp[k]!=2||k==j||vis) continue;
						cnt[4]--;
						cnt[2]-=2;
						tmp[i]-=4,tmp[j]-=2,tmp[k]-=2;
						vis=1;
						res++;
					}
				}
			}
		}
	}
	if(cnt[4]&&cnt[1]>=2){		
		for(int i=l;i<=13;i++){
		    int vis=0;
			if(tmp[i]==4){
				for(int j=l;j<=14;j++){
					if(tmp[j]!=1||vis) continue;
					for(int k=l;k<=14;k++){
						if(tmp[k]!=1||k==j||vis) continue;
						cnt[4]--;
						cnt[1]-=2;
						tmp[i]-=4,tmp[j]-=1,tmp[k]-=1;
						vis=1;
						res++;
					}
				}
			}
		}
	}
	if(cnt[4]&&(cnt[1]==1)&&(cnt[2]==1||cnt[3]==1)){		
		for(int i=l;i<=13;i++){
		    int vis=0;
			if(tmp[i]==4){
				for(int j=l;j<=14;j++){
					if(tmp[j]!=1||vis) continue;
					for(int k=l;k<=14;k++){
						if(tmp[k]<=1||k==i||k==j||vis) continue;
						cnt[4]--;
						cnt[1]-=1;
						if(tmp[k]==2) cnt[2]-=1,tmp[k]-=1,cnt[1]+=1;
						if(tmp[k]==3) cnt[3]-=1,tmp[k]-=1,cnt[2]+=1;
						tmp[i]-=4,tmp[j]-=1;
						vis=1;
						res++;
					}
				}
			}
		}
	}
	if(cnt[3]&&cnt[2]){	
		for(int i=l;i<=13;i++){	
		    int vis=0;
			if(tmp[i]==3){
				for(int j=l;j<=14;j++){
					if(tmp[j]!=2||vis) continue;
					cnt[3]--;cnt[2]--;
					tmp[i]-=3,tmp[j]-=2;
					vis=1;
					res++;
				}
			}
		}
	}
	if(cnt[3]&&cnt[1]){		
		for(int i=l;i<=13;i++){
		    int vis=0;
			if(tmp[i]==3){
				for(int j=l;j<=14;j++){
					if(tmp[j]!=1||vis) continue;
					cnt[3]--;cnt[1]--;
					tmp[i]-=3,tmp[j]-=1;
					vis=1;
					res++;
				}
			}
		}
	}
	for(int i=l;i<=14;i++){
		if(tmp[i]) res++;
	}
	return res;
}
void dfs(int dep){
	if(dep>ans) return;
	int tmp=sanpai();
	if(tmp+dep=2){
		for(int i=l;i<=12;i++){
			for(int j=i+1;j<=12;j++){
				int liang=0;
	  	        for(int k=i;k<=j;k++){
	  	        	if(card[k]<3){
	  	        		liang=1;break;
					  }
				  }
				if(!liang){
					for(int k=i;k<=j;k++){
						card[k]-=3;
						if(card[k]){
							cnt[4]--;
							cnt[1]++;
						}
						else cnt[3]--;
					}
					dfs(dep+1);
					for(int k=i;k<=j;k++){
						if(card[k]){
							card[k]+=3;
							cnt[1]--;
							cnt[4]++;
						}
						else{
							card[k]+=3;
							cnt[3]++;
						}
					}
				} 
	       }
		}	       
	}
    
	if(cnt[2]+cnt[3]+cnt[4]>=3){
		for(int i=l;i<=12;i++){
			for(int j=i+2;j<=12;j++){
				int liang=0;
	  	        for(int k=i;k<=j;k++){
	  	        	if(card[k]<2){
	  	        		liang=1;break;
					  }
				  }
				if(!liang){
					for(int k=i;k<=j;k++){
						card[k]-=2;
						if(card[k]==1){
							cnt[3]--;
							cnt[1]++;
						}
						if(card[k]==2){
							cnt[4]--;
							cnt[2]++;
						}
						if(card[k]==0){
							cnt[2]--;
						}
					}
					dfs(dep+1);
					for(int k=i;k<=j;k++){
						if(card[k]==1){
							cnt[3]++;
							cnt[1]--;
						}
						if(card[k]==2){
							cnt[4]++;
							cnt[2]--;
						}
						if(card[k]==0){
							cnt[2]++;
						}
						card[k]+=2;
					}
				} 
	       }
		}	       
	}
	
	if(cnt[1]+cnt[2]+cnt[3]+cnt[4]>=5){
		for(int i=l;i<=12;i++){
			for(int j=i+4;j<=12;j++){
				int liang=0;
	  	        for(int k=i;k<=j;k++){
	  	        	if(card[k]<1){
	  	        		liang=1;break;
					  }
				  }
				if(!liang){
					for(int k=i;k<=j;k++){
						card[k]-=1;
						if(card[k]==1){
							cnt[2]--;
							cnt[1]++;
						}
						if(card[k]==2){
							cnt[3]--;
							cnt[2]++;
						}
						if(card[k]==0){
							cnt[1]--;
						}
						if(card[k]==3){
							cnt[4]--;
							cnt[3]++;
						}
					}
					dfs(dep+1);
					for(int k=i;k<=j;k++){
						if(card[k]==1){
							cnt[2]++;
							cnt[1]--;
						}
						if(card[k]==2){
							cnt[3]++;
							cnt[2]--;
						}
						if(card[k]==0){
							cnt[1]++;
						}
						if(card[k]==3){
							cnt[4]++;
							cnt[3]--;
						}
						card[k]+=1;
					}
				} 
	       }
		}	       
	}
	
}
int main(){
	cin>>t>>n;
	while(t--){
		init();
		for(int i=1;i<=n;i++){
		    int d,t;
		    cin>>d>>t;
		    if(d>=3&&d<=13) card[d-2]++;
		    if(d==0) card[14]++;
		    if(d==2) card[13]++;
		    if(d==1) card[12]++;
		}
		dfs(0); 
		cout<

 

你可能感兴趣的:(noip 2015 斗地主 大爆搜)