MLE + WA 30 pts
查看原帖
MLE + WA 30 pts
941743
zhujianheng楼主2023/10/4 16:24

code+注释

#include<bits/stdc++.h>
using namespace std;
int ans=0xffffff;
int sum[17];//当前第i种排出现了几次
int T,n; 
void dfs(int x){
	if(x>=ans) return;//下面是顺子
	int s1=0;//单顺子
	for(int i=3;i<=14;i++){
		if(sum[i]==0) s1=0;//顺子结束
		else{
			s1++;
			if(s1>=5){//已经构成顺子,出牌 
				for(int j=i;j>=i-s1+1;j--) sum[j]--;//出顺子
				dfs(x+1);
				for(int j=i;j>=i-s1+1;j--) sum[j]++;//撤回 
			} 
		} 
	}
	int s2=0;//双顺子
	for(int i=3;i<=14;i++){
		if(sum[i]<2) s2=0;//顺子结束
		else{
			s2++;
			if(s2>=3){//已经构成顺子,出牌 
				for(int j=i;j>=i-s1+1;j--) sum[j]-=2;//出顺子
				dfs(x+1);
				for(int j=i;j>=i-s1+1;j--) sum[j]+=2;//撤回 
			} 
		} 
	}
	int s3=0;//三顺子
	for(int i=3;i<=14;i++){
		if(sum[i]<3) s3=0;//顺子结束
		else{
			s3++;
			if(s3>=2){//已经构成顺子,出牌 
				for(int j=i;j>=i-s1+1;j--) sum[j]-=3;//出顺子
				dfs(x+1);
				for(int j=i;j>=i-s1+1;j--) sum[j]+=3;//撤回 
			} 
		} 
	}
	for(int i=2;i<=14;i++){//带牌 
		if(sum[i]<=2) continue;//不能带牌(三张以上才能)
		else if(sum[i]==3){//当前有三张牌,可构成三带一、三带二。 
			sum[i]-=3;//打掉三张 
			for(int j=2;j<=15;j++){//三带一 
				if(sum[j]<=0 || j==i) continue;//若没有牌或带的是自己这种牌(没了),那不能打
				sum[j]--;//三带一 
				dfs(x+1);
				sum[j]++;//回溯 
			}
			for(int j=2;j<=14;j++){//三带二,不选大王小王(15) 
				if(sum[j]<=1 || j==i) continue;//若没有一对牌或带的是自己这种牌(没了),那不能打
				sum[j]-=2;//三带二 
				dfs(x+1);
				sum[j]+=2;//回溯 
			}
			sum[i]+=3;//回溯,选别的牌。 
		}
		else{//有四张以上的牌 
			sum[i]-=3;//1.打掉三张
			for(int j=2;j<=15;j++){//三带一 
				if(sum[j]<=0 || j==i) continue;//若没有牌或带的是自己这种牌(没了),那不能打
				sum[j]--;//三带一 
				dfs(x+1);
				sum[j]++;//回溯 
			}
			for(int j=2;j<=14;j++){//三带二,不选大王小王(15) 
				if(sum[j]<=1 || j==i) continue;//若没有一对牌或带的是自己这种牌(没了),那不能打
				sum[j]-=2;//三带二 
				dfs(x+1);
				sum[j]+=2;//回溯 
			}
			sum[i]+=3;//回溯,选另外的方案。 
			sum[i]-=4;//2.打掉四张 
			for(int k=2;k<=15;k++){//四带二 
				if(sum[k]<=0 || k==i) continue;//若没有一张牌或带的是自己这种牌,不能打
				sum[k]--;//出第一张牌 
				for(int j=2;j<=15;j++){//四带二 
					if(sum[j]<=0 || j==k) continue;//若没有牌或带的是自己这种牌(没了),那不能打
					sum[j]--;//四带二 
					dfs(x+1);
					sum[j]++;//回溯 
				}
				sum[k]++;//回溯 
			}
			for(int k=2;k<=14;k++){//四带四,不选大王小王(15) 
				if(sum[k]<=1 || k==i) continue;//同上
				sum[k]-=2;//同上 
				for(int j=2;j<=14;j++){//四带四 
					if(sum[j]<=1 || j==i) continue;//若没有一对牌或带的是自己这种牌(没了),那不能打
					sum[j]-=2;//四带二 
					dfs(x+1);
					sum[j]+=2;//回溯 
				}
				sum[k]+=2;//同上 
			}
			sum[i]+=4;//回溯,选另外的方案。 
		}
	}
	for(int i=2;i<=15;i++) if(sum[i]) x++;//出光
	ans=min(ans,x);//更新答案 
}
int main(){
	cin>>T>>n;//数据组数和张数 
	while(T--){
		ans=0xffffff;//初始的ans 
		int a,b;//题目中ai和bi 
		memset(sum,0,sizeof(sum));//每回都将次数清0
		for(int i=1;i<=n;i++){ 
			cin>>a>>b;//第i种花色和牌 
			if(a==0) sum[15]++;//大王和小王
			else if(a==1) sum[14]++;//根据牌值排序
			else sum[a]++;//根据牌值排序 
		}
		dfs(0);//搜索
		cout<<ans<<endl;//输出结果 
	}
	return 0;
}
2023/10/4 16:24
加载中...