- /**
- DP
- 对状态编号, 18条边, 每条边可能实线, 也可能虚线, 有2^18种
- MaxScore(x) = max {
- StepScore(rCode, selectedEdgeNum) > 0
- ? StepScore + MaxScore(rCode) //选择的边成三角行
- : RemainScore(x) - MaxScore(rCode) //选择的边不成三角形
- }
- max 函数作用在所有虚线边上。
- **/
- #include <cstdlib>
- #include <iostream>
- using namespace std;
- int maxScore[262144]; //2^18
- //给18条边编号, 边的编号见附图
- const int EDGENUM[10][10] = {
- /*1, 2, 3, 4, 5, 6, 7, 8, 9 10 **/
- -1, 0, 1, -1, -1, -1, -1, -1, -1, -1, //1
- 0, -1, 2, 3, 4, -1, -1, -1, -1, -1, //2
- 1, 2, -1, -1, 5, 6, -1, -1, -1, -1, //3
- -1, 3, -1, -1, 7, -1, 9, 10, -1, -1, //4
- -1, 4 , 5, 7, -1, 8, -1, 11, 12, -1, //5
- -1, -1, 6, -1, 8, -1, -1, -1, 13, 14, //6
- -1, -1, -1, 9, -1, -1, -1, 15, -1, -1, //7
- -1, -1, -1, 10, 11, -1, 15, -1, 16, -1, //8
- -1, -1, -1, -1, 12, 13, -1, 16, -1, 17, //9
- -1, -1, -1, -1, -1, 14, -1, -1, 17, -1, //10
- };
- const int BIT[18] = { 1, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7, 1<<8,
- 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15, 1<<16, 1<<17 };
- struct Triangle {
- int e1, e2, e3;//三条边的编号
- };
- //列举9个三角形
- const Triangle triangle[9] = {
- {0, 1, 2},
- {3, 4, 7}, {2, 4, 5}, {5, 6, 8},
- {9, 10, 15}, {7, 10, 11}, {11, 12, 16}, {8, 12, 13}, {13, 14, 17}
- };
- int StepScore(int x, int i)
- {
- int score = 0;
- for (int j=0; j<9; j++)
- {
- Triangle tri = triangle[j];
- if ( x & BIT[tri.e1] && x & BIT[tri.e2] && x & BIT[tri.e3] )
- {
- if (i == tri.e1 || i == tri.e2 || i == tri.e3)
- score++;
- }
- }
- return score;
- }
- int RemainScore(int x)
- {
- int score = 9;
- for (int j=0; j<9; j++)
- {
- Triangle tri = triangle[j];
- if ( x & BIT[tri.e1] && x & BIT[tri.e2] && x & BIT[tri.e3] )
- {
- score--;
- }
- }
- return score;
- }
- int MaxScore(int x)
- {
- if (maxScore[x] > -1) return maxScore[x];
- if (x == 262143) return maxScore[x] = 0;
- int max = -1, m;
- for (int i=0; i<18; i++)
- {
- if (x & BIT[i]) continue;
- int rCode = x | BIT[i];
- int score = StepScore(rCode, i);
- if (score) m = score + MaxScore(rCode);
- else
- {
- int rScore = RemainScore(x);
- m = rScore - MaxScore(rCode);
- }
- max >?= m;
- }
- return maxScore[x] = max;
- }
- int main(int argc, char *argv[])
- {
- int kase;
- cin>>kase;
- memset(maxScore, -1, sizeof(maxScore));
- for (int i=0; i<kase; i++)
- {
- if (i>0) cout<<endl;
- int games, gNum, moves, a, b;
- cin>>games;
- for (gNum=1; gNum<=games; gNum++)
- {
- cin>>moves;
- int code = 0, turn = 0;//A's turn.
- int scoreOfA = 0;
- for (int j=0; j<moves; j++)
- {
- cin>>a>>b;
- int e = EDGENUM[a-1][b-1];
- code = code | BIT[e];
- int stepScore = StepScore(code, e);
- if (stepScore)
- {
- if (turn == 0) scoreOfA += stepScore;
- } else
- {
- turn = 1 - turn;
- }
- }
- if (turn == 0) scoreOfA += MaxScore(code);
- else scoreOfA += RemainScore(code) - MaxScore(code);
- cout<<"Game "<<gNum<<": ";
- if (scoreOfA > 4) cout<<"A wins."<<endl;
- else cout<<"B wins."<<endl;
- }
- }
- }