POJ 1077 Eight A*算法 八数码问题

    技术2022-05-20  54

    可以使用A*算法解决。

    启发函数f(n)=g(n)+h(n),h(n)=所有棋子到其目标位置的距离和*K,也就是曼哈顿距离*K。

    经过验证,k=1时会超出POJ的时限,k=4时最快,但K=4得到的结果其实不能保证是最短路径,如下面例子:

    8 6 7 2 5 4 3 x 1

    K=1:  ruuldlurddlurrulldrdruldlururdd

    K=2:  urulldrrdluulddruruldldrruldluurrdd

    K=4:ruulddrulldruldrrululddruurddluruldlurrddluurdldruuldrd

    可见poj关于该题的判决是有问题的。

    /*Eight Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12719 Accepted: 5649 Special Judge Description The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 x where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle: 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8 9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12 13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x r-> d-> r-> The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively. Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course). In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three arrangement. Input You will receive a description of a configuration of the 8 puzzle. The description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle 1 2 3 x 4 6 7 5 8 is described by this list: 1 2 3 x 4 6 7 5 8 Output You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Sample Input 2 3 4 1 5 x 7 6 8 Sample Output ullddrurdllurdruldr Source South Central USA 1998*/ #include <stdio.h> #include <algorithm> #include <queue> #include <vector> #include "math.h" #include "string.h" using namespace std; #define MAX_STATE_NUM 362880/*9!*/ #define MAX_HASH_LEN 800000 #define MAX_N 3 typedef struct _HASH_TABLE_ST_ { int iState; int iNext; }HASH_TABLE_ST; int giTargetState = 123456789;/*9 means space*/ HASH_TABLE_ST gastHashState[MAX_HASH_LEN]; char gacTargetState[MAX_N+1][MAX_N] = {'1','2','3','4','5','6','7','8','9'}; struct STATE_ST { int iState; char acState[MAX_N+1][MAX_N]; queue<char> cMoveRecord; friend bool operator<(STATE_ST a,STATE_ST b) { int iLoopX; int iLoopY; int iLenA = 0; int iLenB = 0; for (iLoopX = 0; iLoopX < MAX_N; iLoopX ++) { for (iLoopY = 0; iLoopY < MAX_N; iLoopY ++) { if (a.acState[iLoopX][iLoopY] != gacTargetState[iLoopX][iLoopY]) { //iLenA++; //iLenA += abs(iLoopX - (a.acState[iLoopX][iLoopY]-'0'-1)/3)+abs(iLoopY - (a.acState[iLoopX][iLoopY]-'0'-1)%3);//tle //iLenA += 2*(MAX_N+MAX_N-iLoopY-iLoopX)+abs(iLoopX - (a.acState[iLoopX][iLoopY]-'0'-1)/3)+abs(iLoopY - (a.acState[iLoopX][iLoopY]-'0'-1)%3);//Accept G++875MS iLenA += 2*(abs(iLoopX - (a.acState[iLoopX][iLoopY]-'0'-1)/3)+abs(iLoopY - (a.acState[iLoopX][iLoopY]-'0'-1)%3));//ACCEPT (g++344MS) (C++219ms) } if (b.acState[iLoopX][iLoopY] != gacTargetState[iLoopX][iLoopY]) { //iLenB++; //iLenB += abs(iLoopX - (b.acState[iLoopX][iLoopY]-'0'-1)/3)+abs(iLoopY - (b.acState[iLoopX][iLoopY]-'0'-1)%3); //iLenB += 2*(MAX_N+MAX_N-iLoopY-iLoopX)+abs(iLoopX - (b.acState[iLoopX][iLoopY]-'0'-1)/3)+abs(iLoopY - (b.acState[iLoopX][iLoopY]-'0'-1)%3); iLenB += 2*(abs(iLoopX - (b.acState[iLoopX][iLoopY]-'0'-1)/3)+abs(iLoopY - (b.acState[iLoopX][iLoopY]-'0'-1)%3)); } } } return (a.cMoveRecord.size() + iLenA) > (b.cMoveRecord.size() + iLenB); } }; void InitHashTable() { for (int iLoop = 0; iLoop < MAX_HASH_LEN; iLoop++) { gastHashState[iLoop].iState = 0; gastHashState[iLoop].iNext = MAX_HASH_LEN; } return; } int FindInHashTable(int viState) { int iHashIndex = viState%MAX_HASH_LEN; if (0 == gastHashState[iHashIndex].iState) { return 0; } while (0 != gastHashState[iHashIndex].iState) { if (viState == gastHashState[iHashIndex].iState ) { return 1; } iHashIndex = gastHashState[iHashIndex].iNext; if(MAX_HASH_LEN <= iHashIndex) { break; } } return 0; } int FindAndInsertHashTable(int viState) { int iHashIndex = viState%MAX_HASH_LEN; int iPreIndex = MAX_HASH_LEN; if (0 == gastHashState[iHashIndex].iState) { gastHashState[iHashIndex].iState = viState; return 0; } while (0 != gastHashState[iHashIndex].iState) { if (viState == gastHashState[iHashIndex].iState ) { return 1; } iPreIndex = iHashIndex; iHashIndex = gastHashState[iHashIndex].iNext; if(MAX_HASH_LEN <= iHashIndex) { break; } } iHashIndex = iPreIndex; while (1) { if(MAX_HASH_LEN <= iHashIndex) { iHashIndex = 0; } if (0 == gastHashState[iHashIndex].iState ) { gastHashState[iHashIndex].iState = viState; if(MAX_HASH_LEN > iPreIndex) { gastHashState[iPreIndex].iNext = iHashIndex; } return 0; } iHashIndex++; } return 0; } int Eight_AStar(char *vpSrcState) { int iSpacePosX; int iSpacePosY; STATE_ST stState; STATE_ST stStateUp; STATE_ST stStateDown; STATE_ST stStateLeft; STATE_ST stStateRight; priority_queue<STATE_ST> StateQueue; /*add src state into queue*/ memcpy(stState.acState,vpSrcState,(MAX_N+1)*(MAX_N)*sizeof(char)); stState.iState = atoi(stState.acState[0]); StateQueue.push(stState); while(!StateQueue.empty()) { stStateUp = StateQueue.top(); stStateDown = StateQueue.top(); stStateLeft = StateQueue.top(); stStateRight = StateQueue.top(); StateQueue.pop(); if (1 == FindAndInsertHashTable(stStateUp.iState)) { continue; } if (stStateUp.iState == giTargetState) { while(!stStateUp.cMoveRecord.empty()) { printf("%c",stStateUp.cMoveRecord.front()); stStateUp.cMoveRecord.pop(); } printf("/n"); return 1; } for (iSpacePosX = 0; iSpacePosX < MAX_N; iSpacePosX++) { for (iSpacePosY = 0; iSpacePosY < MAX_N; iSpacePosY++) { if ('9' == stStateUp.acState[iSpacePosX][iSpacePosY]) { break; } } if (iSpacePosY < MAX_N) { break; } } /*up*/ if (0 < iSpacePosX ) { stStateUp.acState[iSpacePosX][iSpacePosY] = stStateUp.acState[iSpacePosX-1][iSpacePosY]; stStateUp.acState[iSpacePosX-1][iSpacePosY] = '9'; stStateUp.iState = atoi(stStateUp.acState[0]); if (0 == FindInHashTable(stStateUp.iState)) { stStateUp.cMoveRecord.push('u'); StateQueue.push(stStateUp); } } /*down*/ if (MAX_N-1 > iSpacePosX ) { stStateDown.acState[iSpacePosX][iSpacePosY] = stStateDown.acState[iSpacePosX+1][iSpacePosY]; stStateDown.acState[iSpacePosX+1][iSpacePosY] = '9'; stStateDown.iState = atoi(stStateDown.acState[0]); if (0 == FindInHashTable(stStateDown.iState)) { stStateDown.cMoveRecord.push('d'); StateQueue.push(stStateDown); } } /*left*/ if (0 < iSpacePosY ) { stStateLeft.acState[iSpacePosX][iSpacePosY] = stStateLeft.acState[iSpacePosX][iSpacePosY-1]; stStateLeft.acState[iSpacePosX][iSpacePosY-1] = '9'; stStateLeft.iState = atoi(stStateLeft.acState[0]); if (0 == FindInHashTable(stStateLeft.iState)) { stStateLeft.cMoveRecord.push('l'); StateQueue.push(stStateLeft); } } /*right*/ if (MAX_N-1 > iSpacePosY ) { stStateRight.acState[iSpacePosX][iSpacePosY] = stStateRight.acState[iSpacePosX][iSpacePosY+1]; stStateRight.acState[iSpacePosX][iSpacePosY+1] = '9'; stStateRight.iState = atoi(stStateRight.acState[0]); if (0 == FindInHashTable(stStateRight.iState)) { stStateRight.cMoveRecord.push('r'); StateQueue.push(stStateRight); } } } return 0; } int main(void) { char cInput; int iLoop; int iLoop1; int iReverseNum= 0; char acSrcState[MAX_N+1][MAX_N]; InitHashTable(); for (iLoop = 0; iLoop < 9;iLoop++) { scanf(" %c",&cInput); if ('1' <= cInput && '8' >= cInput) { acSrcState[iLoop/3][iLoop%3] = cInput; } else//('x' == cInput) { acSrcState[iLoop/3][iLoop%3] = '9'; } } acSrcState[3][0] = '/0'; for (iLoop = 1; iLoop < 9;iLoop++) { if ('9' == acSrcState[iLoop/3][iLoop%3]) { continue; } for (iLoop1 = 0; iLoop1 < iLoop;iLoop1++) { if ('9' == acSrcState[iLoop1/3][iLoop1%3]) { continue; } if (acSrcState[iLoop1/3][iLoop1%3] > acSrcState[iLoop/3][iLoop%3]) { iReverseNum++; } } } if (1 == iReverseNum%2) { printf("unsolvable"); } else { Eight_AStar(acSrcState[0]); } return 0; }


    最新回复(0)