朝日新聞2004年11月13日パズルパーク解答

勝ち点が11になるのは,3勝0敗2分けになることは直感で判る。

3勝2分けを前提に作ったプログラムの実行結果は以下の通り。

  : ABCDEF
A :  ○△△○○
B : × △○○○
C : △△ △○○
D : △×△ ○○
E : ×××× ○
F : ××××× 

loop cnt:59049, find:1

プログラムのソースは以下の通り。重複除去は星取表の勝ち点を文字列に変換してSTLのsetで既に出現したかどうか判断する。

#include "puzutl.h"
#include <math.h>

set<string> dupres;             // 重複結果を取り除くために利用する
int star[6][6];                 // 星取り表(0:勝ち点0,1:勝ち点1,3:勝ち点3を設定)
int cnta[3] = { 0, 1, 3};       // 星取り表行方向の勝ち点可能性
int cntb[3] = { 3, 1, 0};       // 星取り表列方向の勝ち点可能性
struct struct_team {
  int katiten;                  // star[][]に設定した勝ち点の行合計
  int idx;                      // 勝ち点でソートしたとき,star[][]のどの行を指していたかを記録する
}team[6];
// 以下のような星取表を仮定する。
// Aチームを配列の0行目に仮定する。
//  AT1T2T3T4T5
// A ○○○△△
// T1× a b c d
// T2×    e f g
// T3×      h i
// T4△        j
// T5△
int cmpkatiten( const void* a, const void* b) { return -(((struct_team*)a)->katiten - ((struct_team*)b)->katiten);}// 勝ち点を降順にソートする
cstring stars( int v) { cstring s[] = {"×","△","*","○"}; return s[v];}
YesNo isdupresult()             // 重複結果か?
{
  char buf[256];
  int i=0;
  for( int x=0; x< 6; x++) {
    for( int y=0; y< 6; y++) {
      buf[i++] = '0'+star[team[x].idx][team[y].idx];
    }
  }
  if( dupres.find(buf) != dupres.end()) {
    return YES;
  }
  dupres.insert(buf);
  return NO;
}
int main( int argc, cstring argv[])
{
  // T0チームの勝ち点は○○○△△と判るので星取り表を埋めてしまう。
  star[0][1] = 3;
  star[0][2] = 3;
  star[0][3] = 3;
  star[0][4] = 1;
  star[0][5] = 1;
  star[1][0] = 0;
  star[2][0] = 0;
  star[3][0] = 0;
  star[4][0] = 1;
  star[5][0] = 1;
  int           cnt = 0, find = 0;
  // 星取り表の残りの部分を虱潰す。
  for( int a=0; a< 3; a++) {
    star[1][2] = cnta[a];       // 一方が勝ち点3なら
    star[2][1] = cntb[a];       // 反対側は勝ち点0になる。
    for( int b=0; b< 3; b++) {
      star[1][3] = cnta[b];
      star[3][1] = cntb[b];
      for( int c=0; c< 3; c++) {
        star[1][4] = cnta[c];
        star[4][1] = cntb[c];
        for( int d=0; d< 3; d++) {
          star[1][5] = cnta[d];
          star[5][1] = cntb[d];
          for( int e=0; e< 3; e++) {
            star[2][3] = cnta[e];
            star[3][2] = cntb[e];
            for( int f=0; f< 3; f++) {
              star[2][4] = cnta[f];
              star[4][2] = cntb[f];
              for( int g=0; g< 3; g++) {
                star[2][5] = cnta[g];
                star[5][2] = cntb[g];
                for( int h=0; h< 3; h++) {
                  star[3][4] = cnta[h];
                  star[4][3] = cntb[h];
                  for( int i=0; i< 3; i++) {
                    star[3][5] = cnta[i];
                    star[5][3] = cntb[i];
                    for( int j=0; j< 3; j++) {
                      star[4][5] = cnta[j];
                      star[5][4] = cntb[j];
                      // 各チームの勝ち点を求める。
                      team[0].katiten = 11;
                      team[1].katiten = star[1][0] + star[1][1] + star[1][2] + star[1][3] + star[1][4] + star[1][5];
                      team[2].katiten = star[2][0] + star[2][1] + star[2][2] + star[2][3] + star[2][4] + star[2][5];
                      team[3].katiten = star[3][0] + star[3][1] + star[3][2] + star[3][3] + star[3][4] + star[3][5];
                      team[4].katiten = star[4][0] + star[4][1] + star[4][2] + star[4][3] + star[4][4] + star[4][5];
                      team[5].katiten = star[5][0] + star[5][1] + star[5][2] + star[5][3] + star[5][4] + star[5][5];
                      team[0].idx = 0; team[1].idx = 1; team[2].idx = 2; team[3].idx = 3; team[4].idx = 4; team[5].idx = 5;
                      qsort( team, 6, sizeof(struct_team), cmpkatiten);
                      if( team[0].katiten == 11 && team[1].katiten == 10 && team[2].katiten == 9 && team[3].katiten == 8 && team[4].katiten == 3 && team[5].katiten == 0) {
                        if( !isdupresult()) { // 星取結果から重複を除去する。
                          find++;
                          ps( "  : ABCDEF\n");
                          for( int x=0; x< 6; x++) {
                            ps( "%-.2s : ", "ABCDEF"+x*2);
                            for( int y=0; y< 6; y++) {
                              if( x == y) ps( " ");
                              else ps( "%s", stars(star[team[x].idx][team[y].idx]));
                            }
                            ps( "\n");
                          }
                          ps( "\n");
                        }
                      }
                      cnt++; // ここに制約処理を書く
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  ps( "loop cnt:%d, find:%d\n", cnt, find);
  return    0;
}