AOJ : 2084 - Hit and Blow

問題概要

http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=2084
ヒット&ブローというゲームがあります. ヒット&ブローは次の問題で確認してください. ( http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=0025&lang=jp )
AさんとBさんがいて, Aさんはある秘密の4ケタの数字を持っています.(この数字は, 各桁の数字が異なる4ケタの数) Bさんがある数字を発言すると, Aさんは, 自分が持っている秘密の数とBさんの数を見て, ヒット数とブロー数を返してくれます.

このようなルールのとき, ゲームのプレイ履歴が入力として与えられます. この履歴を見て, ゲーム終了後にBさんはAさんの秘密の数を1通りに確定させることができるかを答える問題です.
もし確定できるならば, その数を出力. できないとしても, さらにBさんがもう一回数字を発言することで, 1通りに確定させることができるならば, Bさんが発言する数字を出力. そのどちらでもないならば, ???? と出力.

アルゴリズム

全探索で解きましょう.
OBOGの解法が僕と全く同じだったので, そちらを参考にしてください.
Day2-A問題
( http://acm-icpc.aitea.net/index.php?2007%2FPractice%2F%B2%C6%B9%E7%BD%C9%2F%B9%D6%C9%BE )

プログラム

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

#define REP(i,n,m) for(int i=n;i<m;i++)
#define rep(i,n) REP(i,0,n)

//ヒット数を返す
int hit(string a,string b){
  int res = 0;
  rep(i,4) if(a[i] == b[i]) res++;
  return res;
}

//ブロー数を返す
int blow(string a,string b){
  int res = 0;
  rep(i,4) rep(j,4){
    if(i == j) continue;
    if(a[i] == b[j]){
      res++;
      break;
    }
  }

  return res;
}

int main(void){
  vector<string> s,init;

  //4ケタの各桁が異なる数を列挙する
  rep(i,10) rep(j,10) rep(k,10) rep(l,10) {
    if(i != j && i != k && i != l && j != k && j != l && k != l){
      string str = "";
      str += '0' + i;
      str += '0' + j;
      str += '0' + k;
      str += '0' + l;
      init.push_back(str);
    }
  }

  int n;
  while(cin>>n,n){
    s = init;
    while(n--){
      string str;
      int h,b;
      cin>>str>>h>>b;

      vector<string> next;
      rep(i,s.size()){
        if(hit(str,s[i]) == h && blow(str,s[i]) == b){
          next.push_back(s[i]);
        }
      }
      s = next;
    }

    if(s.empty()){
      cout<<"????\n";
    }
    else if(s.size() == 1){
      cout<<s[0]<<endl;
    }
    else{
      bool ansFlg;
      rep(i,init.size()){
        bool used[5][5];
        memset(used,0,sizeof(used));
        ansFlg = true;

        rep(j,s.size()){
          int h = hit(init[i],s[j]);
          int b = blow(init[i],s[j]);
          if(used[h][b]){
            ansFlg = false;
            break;
          }
          used[h][b] = true;
        }

        if(ansFlg){
          cout<<init[i]<<endl;
          break;
        }
      }
      if(!ansFlg) cout<<"????\n";
    }
  }

  return 0;
}