2020牛客暑期多校训练营(第八场)G题Game SET(折半搜索)
2020牛客暑期多校训练营(第八场)G题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\n",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\n",h,ans1,ans2,ans3);
else{
printf("Case #%d: -1\n",h);
}
}
}