比赛描述
输入
The input will consist of one to twelve data sets, followed by a line containing only 0.
The first line of a dataset contains the number, t, of turns reported, 2 ≤ t ≤ 15.
The next line contains four blank separated strings for the hands of players 1, 2, and 3, followed by the cards for the gang.
The remaining t lines of the data set contain the data for each turn in order. Each line contains three blank separated tokens: the number of the player interrogated, the string of interrogation letters, and the answer provided.
All letter strings will contain only capital letters from A to R, in strictly increasing alphabetical order. The same interrogation string may appear in more than one turn of a game.
输出
There is one line of output for each data set. The line contains the single character "?" if no player can be sure of the gang after all the turns listed. If a player can determine the gang, the line contains the earliest turn after which one or more players can be sure of the answer.
样例输入
9
DGJLP EFOQR ACHMN BIK
2 BJK 0
3 ABK 1
2 DEF 2
2 EIL 1
3 FIP 0
1 GMO 1
2 OQR 3
3 ADQ 1
1 EGJ 2
3
ABCDE FGHIJ KLMNO PQR
3 BKQ 1
1 ADE 3
2 CHJ 2
0
样例输出
8
?
题目来源
ACM Mid-Central Regional 2009
#include<iostream> using namespace std; const int PLAYERS = 3, // check against final problem statement! MAX_TURNS = 15, HAND = 5, HID = 3, UNK = HID+HAND*(PLAYERS-1); int turns; char quest[MAX_TURNS][3+1], // interrogations hand[PLAYERS + 1][5+1], //actual hands, gang at end maybe[PLAYERS + 1][HAND+1]; //possible hands, gang char unk[UNK]; // letters not in one player's hand int who[MAX_TURNS], // who interrogated matches[MAX_TURNS], // matches in interogation used[PLAYERS+1]; // amount of maybe hand filled int solved; // max turns needed for current player for comb. so far int Max(int a,int b); void solve(int i,char unk[]); int countConsistent(char choice[][HAND+1]); int countDups(char a1[],char a2[]); int main() { //freopen("in.txt","r",stdin); int i,j; int bestSolved; while(scanf("%d",&turns)!=EOF && turns>0) { for(i=0;i<=PLAYERS;i++) scanf("%s",&hand[i]); int t; for(t=0;t<turns;t++) { scanf("%d",&who[t]); who[t]--; // internal 0 based scanf("%s",&quest[t]); scanf("%d",&matches[t]); } bestSolved=MAX_TURNS; int p; char unkStr[18-5+1]; for(p=0;p<PLAYERS;p++) { memset(unkStr,'\0',sizeof(unkStr)); for(j=0;j<=PLAYERS;j++){ if(j!=p) strcat(unkStr,hand[j]); } strcpy(maybe[p],hand[p]); // player knows own used[p] = HAND; // no further characters to choose solved = 0; // after recursion max turns to eliminate a maybe solve(0,unkStr); memset(maybe[p],'\0',sizeof(maybe[p])); used[p]=0; if(solved<bestSolved) bestSolved=solved; } if(bestSolved<turns) printf("%d\n",bestSolved+1); else printf("?\n"); }//end while return 0; }//end main() int Max(int a,int b) { return (a>b)?a:b; } // accumulate combinations recursively, check when one is complete void solve(int i,char unk[]) { if(i==(18-5)){ // assigned all choices, now check if (maybe[PLAYERS][0] == unk[i-HID]) return; //match end gang char solved = Max(solved, countConsistent(maybe)); } else{ int j; for(j=0;j<=PLAYERS;j++){ if((j<PLAYERS && used[j]<5) || (j==PLAYERS && used[j]<3)){ //add char to partial hand maybe[j][used[j]]=unk[i]; used[j]++; solve(i+1,unk); used[j]--; // undo change before trying next player } } } } // return first inconsistent turn (0 based) or total turns if consistent int countConsistent(char choice[][HAND+1]) { int t=0; while(t<turns && countDups(choice[who[t]],quest[t])==matches[t]) t++; return t; } int countDups(char a1[],char a2[]) { int i,j; int n=0; for(i=0;i<5;i++){ for(j=0;j<3;j++) if(a1[i]==a2[j]) n++; } return n; }