HDU - 1043 Eight(bfs打表)
生活随笔
收集整理的這篇文章主要介紹了
HDU - 1043 Eight(bfs打表)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:八數碼經典問題,給出一個3*3的矩陣,其中隨機分布著1~8的數字以及一個空位(我們用x來表示空位),在整個矩陣中,每一次操作都可以將x和他附近的方塊互換,問經過多少次操作可以將當前的狀態變為順序狀態,即
1? ?2? ?3
4? ?5? ?6
7? ?8? ?x
求所需操作的最小次數以及每次的步驟
題目分析:一看到這個題目首先想到每一種情況都可以表示為一種狀態,一提到狀態我們就可以用bfs進行展開,這個題不得不說我優化了一個下午,一開始沒多想,直接用A*做的,想連一下A*算法,結果寫完之后T掉了,我就感覺我的估價函數找的不太對,就去網上搜了大佬的博客,比這寫了一下估價函數,結果變成WA了,有點自閉,就去網上搜了搜八種方法解八數碼問題,就選了現在的這個,先用bfs打個表,然后就可以O(1)查詢了,省去了大量的bfs步驟,不過我在打表的時候用到了unordered_map,但是poj不讓用這個東西。。所以在poj上還是T掉了,在hdu上的以200多ms的時間A掉了,我又試了試用map交了一發,在hdu上還是A了,只不過時間變成了500ms。。因為網上的正解都是用了康托展開維護狀態的,但我不會,只能用最菜的map來維護所謂的雙向哈希了,預處理bfs打個路徑表,然后直接問什么輸出什么就可以了
代碼:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=4e5+100;const int b[4][2]={0,1,0,-1,1,0,-1,0};const char p[5]="lrud";const string target="123456780";unordered_map<string,int>vis;struct Node {int pre;int dir;Node(int PRE,int DIR){pre=PRE;dir=DIR;}Node(){} }path[N];void bfs() {int cnt=0;//用一個cnt變量輔助維護模擬鏈表vis.clear();queue<string>q;q.push(target);//以最終狀態為起點,bfs展開即可,時間復雜度為9!,不到4e5path[cnt].pre=-1;path[cnt].dir=-1;vis[target]=cnt++;while(!q.empty()){string cur=q.front();q.pop();int pos;for(pos=0;pos<9;pos++)if(cur[pos]=='0')break;int x=pos/3;int y=pos%3;for(int i=0;i<4;i++){int xx=x+b[i][0];int yy=y+b[i][1];if(xx<0||yy<0||xx>=3||yy>=3)continue;int ppos=xx*3+yy;string temp=cur;swap(temp[pos],temp[ppos]);if(vis[temp])continue;path[cnt].pre=vis[cur];path[cnt].dir=i;vis[temp]=cnt++;q.push(temp);}} }//2 3 4 //1 5 x //7 6 8int main() { // freopen("input.txt","r",stdin);bfs();//預處理打表char s[5];while(scanf("%s",s)!=EOF){string str;if(s[0]=='x')str+='0';elsestr+=s[0];for(int i=0;i<8;i++){scanf("%s",s);if(s[0]=='x')str+='0';elsestr+=s[0];}if(!vis[str])//如果該狀態遍歷不到,則無解printf("unsolvable\n");else//如果該狀態能遍歷到,則直接輸出路徑即可{int k=vis[str];while(k!=-1){putchar(p[path[k].dir]);k=path[k].pre;}putchar('\n');}}return 0; }?
總結
以上是生活随笔為你收集整理的HDU - 1043 Eight(bfs打表)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ - 2248 Addition
- 下一篇: 康托展开与逆展开(原理+模板)