2020牛客暑期多校训练营(第八场)G题Game SET(折半搜索)

2020牛客暑期多校训练营(第八场)G题Game SET(折半搜索)

Game SET

题意:一副牌,一共4个特征,每个特征有3种,所以其所有组合共81(3^4)个,要求取3张牌,对于三张牌的每个特征都要满足3卡相等或都不相等,其中还有第4种特殊的种类*可以表示任意种类,给256个牌,求出符合要求的方案。

题解:官方题解是21张牌中必然存在答案,3层循环暴力直接过,太菜找不到不知道结论,用折半搜索过的,我们先可以把所有种类hash成数字,然后枚举两张卡片,去找符合要求的第3张卡片是否存在即可,符合条件的卡片可以dfs暴力枚举,没有太多,就dfs稍微有点绕,具体可以看我代码。

#include<iostream>
#include<map>
#include<vector>
using namespace std;
int t,n,cnt,a[307][5];
string s[307];
struct madoka{
	int a,b,c,d;
	bool operator < (const madoka & o) const
    {
    	if(a==o.a){
			if(b==o.b){
				if(c==o.c){
					return d>o.d;
				}
				return c>o.c;
			}
			return b>o.b;
    	}
        return a>o.a;
    }
};
map<madoka,int>ma;
vector<int>ho[100007];
void go(string s,int p){
	int t=0;
	string lin;
	for(int i=0;i<s.length();i++){
		if(s[i]=='['){
			lin="";
			t++;
		}
		else if(s[i]==']'){
			if(t==1){
				if(lin=="*"){
					a[p][t]=0;
				}
				else if(lin=="one"){
					a[p][t]=1;
				}
				else if(lin=="two"){
					a[p][t]=2;
				}
				else{
					a[p][t]=3;
				}
			}
			if(t==2){
				if(lin=="*"){
					a[p][t]=0;
				}
				else if(lin=="diamond"){
					a[p][t]=1;
				}
				else if(lin=="squiggle"){
					a[p][t]=2;
				}
				else{
					a[p][t]=3;
				}
			}
			if(t==3){
				if(lin=="*"){
					a[p][t]=0;
				}
				else if(lin=="solid"){
					a[p][t]=1;
				}
				else if(lin=="striped"){
					a[p][t]=2;
				}
				else{
					a[p][t]=3;
				}
			}
			if(t==4){
				if(lin=="*"){
					a[p][t]=0;
				}
				else if(lin=="red"){
					a[p][t]=1;
				}
				else if(lin=="green"){
					a[p][t]=2;
				}
				else{
					a[p][t]=3;
				}
			}
		}
		else{
			lin+=s[i];
		}
	}
}
int fin(int i,int j,int p){
	if(a[i][p]==0||a[j][p]==0){
		return 4;
	}
	else{
		if(a[i][p]==a[j][p])return a[i][p];
		else{
			return 6-a[i][p]-a[j][p];
		}
	}
}

int dfs(int n,int m,int p,int a,int b,int c,int d){
	if(p==5){
		int o=ma[{a,b,c,d}];
		for(int i=0;i<ho[o].size();i++){
			if(ho[o][i]!=n&&ho[o][i]!=m){
				return ho[o][i];
			}
		}
		return 0;
	}
	int ans=0;
	if(p==1){
		if(a==4){
			ans=max(ans,dfs(n,m,p+1,0,b,c,d));
			ans=max(ans,dfs(n,m,p+1,1,b,c,d));
			ans=max(ans,dfs(n,m,p+1,2,b,c,d));
			ans=max(ans,dfs(n,m,p+1,3,b,c,d));
		}
		else{
			ans=max(ans,dfs(n,m,p+1,0,b,c,d));
			ans=max(ans,dfs(n,m,p+1,a,b,c,d));
		}
	}
	else if(p==2){
		if(b==4){
			ans=max(ans,dfs(n,m,p+1,a,0,c,d));
			ans=max(ans,dfs(n,m,p+1,a,1,c,d));
			ans=max(ans,dfs(n,m,p+1,a,2,c,d));
			ans=max(ans,dfs(n,m,p+1,a,3,c,d));
		}
		else{
			ans=max(ans,dfs(n,m,p+1,a,0,c,d));
			ans=max(ans,dfs(n,m,p+1,a,b,c,d));
		}
	}
	else if(p==3){
		if(c==4){
			ans=max(ans,dfs(n,m,p+1,a,b,0,d));
			ans=max(ans,dfs(n,m,p+1,a,b,1,d));
			ans=max(ans,dfs(n,m,p+1,a,b,2,d));
			ans=max(ans,dfs(n,m,p+1,a,b,3,d));
		}
		else{
			ans=max(ans,dfs(n,m,p+1,a,b,0,d));
			ans=max(ans,dfs(n,m,p+1,a,b,c,d));
		}
	}
	else{
		if(d==4){
			ans=max(ans,dfs(n,m,p+1,a,b,c,0));
			ans=max(ans,dfs(n,m,p+1,a,b,c,1));
			ans=max(ans,dfs(n,m,p+1,a,b,c,2));
			ans=max(ans,dfs(n,m,p+1,a,b,c,3));
		}
		else{
			ans=max(ans,dfs(n,m,p+1,a,b,c,0));
			ans=max(ans,dfs(n,m,p+1,a,b,c,d));
		}
	}
	return ans;
}

int main(){
	//ios::sync_with_stdio(0);
	//cin.tie(0);
	//cout.tie(0);
	int h=0;
	scanf("%d",&t);
	while(t--){
		h++;
		ma.clear();
		for(int i=0;i<=10000;i++)ho[i].clear();
		cnt=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			cin>>s[i];
			go(s[i],i);
			if(!ma[{a[i][1],a[i][2],a[i][3],a[i][4]}]){
				ma[{a[i][1],a[i][2],a[i][3],a[i][4]}]=++cnt;
			};
			ho[ma[{a[i][1],a[i][2],a[i][3],a[i][4]}]].push_back(i);
		}
		int ans1=0,ans2=0,ans3=0,ok=0;
		for(int i=1;i<=n;i++){
			for(int j=i+1;j<=n;j++){
				int sub[5];
				for(int p=1;p<=4;p++){
					sub[p]=fin(i,j,p);
				}
				//printf("i=%d,j=%d %d %d %d %d
",i,j,sub[1],sub[2],sub[3],sub[4]);
				ok=dfs(i,j,0,sub[1],sub[2],sub[3],sub[4]);
				if(ok){
					ans1=i;
					ans2=j;
					ans3=ok;
					break;
				}
			}
			if(ok)break;
		}
		if(ok)printf("Case #%d: %d %d %d
",h,ans1,ans2,ans3);
		else{
			printf("Case #%d: -1
",h);
		}
	}
}

原文地址:https://www.cnblogs.com/whitelily/p/13430466.html