用极小极大值算法解决比较直观,但是效率太低,即使使用了α-β剪枝,效率仍然很低,勉强ACCEPT, 因为这种方法本质上是深度搜索,会有大量的重复计算,如果像DP那样将计算过的状态记录下来,则还有进一步优化的空间。 /*Triangle War Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 1567 Accepted: 623 Description Triangle War is a two-player game played on the following triangular grid: Two players, A and B, take turns filling in any dotted line connecting two dots, with A starting first. Once a line is filled, it cannot be filled again. If the line filled by a player completes one or more triangles, she owns the completed triangles and she is awarded another turn (i.e. the opponent skips a turn). The game ends after all dotted lines are filled in, and the player with the most triangles wins the game. The difference in the number of triangles owned by the two players is not important. For example, if A fills in the line between 2 and 5 in the partial game on the left below: Then, she owns the triangle labelled A and takes another turn to fill in the line between 3 and 5. B can now own 3 triangles (if he wishes) by filling in the line between 2 and 3, then the one between 5 and 6, and finally the one between 6 and 9. B would then make one more move before it is A's turn again. In this problem, you are given a number of moves that have already been made. From the partial game, you should determine which player will win assuming that each player plays a perfect game from that point on. That is, assume that each player always chooses the play that leads to the best possible outcome for himself/herself. Input You will be given a number of games in the input. The first line of input is a positive integer indicating the number of games to follow. Each game starts with an integer 6 <= m <= 18 indicating the number of moves that have been made in the game. The next m lines indicate the moves made by the two players in order, each of the form i j (with i < j) indicating that the line between i and j is filled in that move. You may assume that all given moves are legal. Output For each game, print the game number and the result on one line as shown below. If A wins, print the sentence "A wins." If B wins, print "B wins." Sample Input 4 6 2 4 4 5 5 9 3 6 2 5 3 5 7 2 4 4 5 5 9 3 6 2 5 3 5 7 8 6 1 2 2 3 1 3 2 4 2 5 4 5 10 1 2 2 5 3 6 5 8 4 7 6 10 2 4 4 5 4 8 7 8 Sample Output Game 1: B wins. Game 2: A wins. Game 3: A wins. Game 4: B wins. Source East Central North America 1999*/ #include <stdio.h> #include <stdlib.h> #include "string.h" #define TRIANGLE_NUM 10//9+1 #define LINE_NUM 18 #define POSITIVE_INFINITE 0XFFFFFFF #define NEGITIVE_INFINITE -0XFFFFFFF #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) typedef struct _LINE_ST_ { char acEndpoint[2]; char cFilled;/*0:not 1:filled*/ char cBelongedTriangleNum; char acTriangleIndex[2]; }LINE_ST; char gacTriangleLineNum[TRIANGLE_NUM];//三角形已有的边数 LINE_ST gastLine[LINE_NUM];//边,与三角形的关系 int giLineIndex; int giNumMax; int giNumMin; int Min_Value(int viAlpha,int viBeta,int viUtility,int viDeepth); int Max_Value(int viAlpha,int viBeta,int viUtility,int viDeepth) { int iValue = NEGITIVE_INFINITE; int iValueNext; int iLoop; int iLoop1; int iUtility; if (LINE_NUM == viDeepth ) { return viUtility; } for (iLoop = 0; iLoop < LINE_NUM; iLoop++) { if (0 == gastLine[iLoop].cFilled ) { iUtility = 0; gastLine[iLoop].cFilled = 1; for (iLoop1 = 0; iLoop1 < gastLine[iLoop].cBelongedTriangleNum; iLoop1++) { gacTriangleLineNum[gastLine[iLoop].acTriangleIndex[iLoop1]]++; if (3 == gacTriangleLineNum[gastLine[iLoop].acTriangleIndex[iLoop1]]) { iUtility++; } } giNumMax += iUtility; if (5 <= giNumMax) { giNumMax -= iUtility; gastLine[iLoop].cFilled = 0; for (iLoop1 = 0; iLoop1 < gastLine[iLoop].cBelongedTriangleNum; iLoop1++) { gacTriangleLineNum[gastLine[iLoop].acTriangleIndex[iLoop1]]--; } return POSITIVE_INFINITE; } if (0 < iUtility) { iValueNext = Max_Value(viAlpha,viBeta,viUtility+iUtility,viDeepth+1); } else { iValueNext = Min_Value(viAlpha,viBeta,viUtility+iUtility,viDeepth+1); } if (iValue < iValueNext) { iValue = iValueNext; giLineIndex = iLoop; } gastLine[iLoop].cFilled = 0; for (iLoop1 = 0; iLoop1 < gastLine[iLoop].cBelongedTriangleNum; iLoop1++) { gacTriangleLineNum[gastLine[iLoop].acTriangleIndex[iLoop1]]--; } giNumMax -= iUtility; if (iValue >= viBeta) { return iValue; } viAlpha = MAX(viAlpha,iValue); } } return iValue; } int Min_Value(int viAlpha,int viBeta,int viUtility,int viDeepth) { int iValue = POSITIVE_INFINITE; int iLoop; int iLoop1; int iUtility; if (LINE_NUM == viDeepth ) { return viUtility; } for (iLoop = 0; iLoop < LINE_NUM; iLoop++) { if (0 == gastLine[iLoop].cFilled ) { iUtility = 0; gastLine[iLoop].cFilled = 1; for (iLoop1 = 0; iLoop1 < gastLine[iLoop].cBelongedTriangleNum; iLoop1++) { gacTriangleLineNum[gastLine[iLoop].acTriangleIndex[iLoop1]]++; if (3 == gacTriangleLineNum[gastLine[iLoop].acTriangleIndex[iLoop1]]) { iUtility++; } } giNumMin += iUtility; if (5 <= giNumMin) { giNumMin -= iUtility; gastLine[iLoop].cFilled = 0; for (iLoop1 = 0; iLoop1 < gastLine[iLoop].cBelongedTriangleNum; iLoop1++) { gacTriangleLineNum[gastLine[iLoop].acTriangleIndex[iLoop1]]--; } return NEGITIVE_INFINITE; } if(0 < iUtility) { iValue = MIN(iValue,Min_Value(viAlpha,viBeta,viUtility-iUtility,viDeepth+1)); } else { iValue = MIN(iValue,Max_Value(viAlpha,viBeta,viUtility-iUtility,viDeepth+1)); } gastLine[iLoop].cFilled = 0; for (iLoop1 = 0; iLoop1 < gastLine[iLoop].cBelongedTriangleNum; iLoop1++) { gacTriangleLineNum[gastLine[iLoop].acTriangleIndex[iLoop1]]--; } giNumMin -= iUtility; if (iValue <= viAlpha) { return iValue; } viBeta = MIN(viBeta,iValue); } } return iValue; } int Alpha_Beta_Search(int viUtility,int viDeepth) { return Max_Value(NEGITIVE_INFINITE,POSITIVE_INFINITE,viUtility,viDeepth); } int TriangleWarmain(void) { int iNumA ; int iNumB ; int iUtility; int iTurn; int iLoopCase; int iLoopMove; int iLoopLine; int iLoop; int iCaseNum; int iMoveNum; int iEndPoint1; int iEndPoint2; LINE_ST astLine[LINE_NUM] = {{{2,3},0,2,{1,3}},{{2,5},0,2,{2,3}},{{3,5},0,2,{3,4}},/ {{4,8},0,2,{5,6}},{{5,6},0,2,{4,8}},{{5,8},0,2,{6,7}},/ {{5,9},0,2,{7,8}},{{6,9},0,2,{8,9}},{{4,5},0,2,{2,6}},/ {{1,2},0,1,{1,0}},{{1,3},0,1,{1,0}},{{2,4},0,1,{2,0}},/ {{3,6},0,1,{4,0}},{{4,7},0,1,{5,0}},{{6,10},0,1,{9,0}},/ {{7,8},0,1,{5,0}},{{8,9},0,1,{7,0}},{{9,10},0,1,{9,0}}}; scanf("%d",&iCaseNum); for(iLoopCase = 1; iLoopCase <= iCaseNum; iLoopCase++) { iNumA = 0; iNumB = 0; iTurn = 0; memcpy(gastLine,astLine,LINE_NUM*sizeof(LINE_ST)); memset(gacTriangleLineNum,0,TRIANGLE_NUM*sizeof(char)); scanf("%d",&iMoveNum); for (iLoopMove = 0; iLoopMove < iMoveNum; iLoopMove++) { iUtility = 0; scanf("%d %d",&iEndPoint1,&iEndPoint2); for (iLoopLine = 0; iLoopLine < LINE_NUM; iLoopLine++) { if (iEndPoint1 == gastLine[iLoopLine].acEndpoint[0] &&iEndPoint2 == gastLine[iLoopLine].acEndpoint[1]) { gastLine[iLoopLine].cFilled = 1; for (iLoop = 0; iLoop < gastLine[iLoopLine].cBelongedTriangleNum;iLoop++) { gacTriangleLineNum[gastLine[iLoopLine].acTriangleIndex[iLoop]]++; if (3 == gacTriangleLineNum[gastLine[iLoopLine].acTriangleIndex[iLoop]]) { iUtility++; } } if (0 == iUtility ) { iTurn = iTurn ^1; break; } if (0 == iTurn) {//A iNumA += iUtility; } else {//B iNumB += iUtility; } break; } } } /************************************************************************/ /* resolve */ /************************************************************************/ if (0 == iTurn) {//A iUtility = iNumA - iNumB; giNumMax = iNumA; giNumMin = iNumB; } else {//B iUtility = iNumB - iNumA; giNumMax = iNumB; giNumMin = iNumA; } iUtility = Alpha_Beta_Search(iUtility,iMoveNum); if ((0 == iTurn&&0 < iUtility) ||(1 == iTurn&&0 > iUtility)) { printf("Game %d: A wins./n",iLoopCase); } else { printf("Game %d: B wins./n",iLoopCase); } } return 0; }