HDU - 1043 Eight(bfs打表)
題目鏈接:點(diǎn)擊查看
題目大意:八數(shù)碼經(jīng)典問(wèn)題,給出一個(gè)3*3的矩陣,其中隨機(jī)分布著1~8的數(shù)字以及一個(gè)空位(我們用x來(lái)表示空位),在整個(gè)矩陣中,每一次操作都可以將x和他附近的方塊互換,問(wèn)經(jīng)過(guò)多少次操作可以將當(dāng)前的狀態(tài)變?yōu)轫樞驙顟B(tài),即
1? ?2? ?3
4? ?5? ?6
7? ?8? ?x
求所需操作的最小次數(shù)以及每次的步驟
題目分析:一看到這個(gè)題目首先想到每一種情況都可以表示為一種狀態(tài),一提到狀態(tài)我們就可以用bfs進(jìn)行展開(kāi),這個(gè)題不得不說(shuō)我優(yōu)化了一個(gè)下午,一開(kāi)始沒(méi)多想,直接用A*做的,想連一下A*算法,結(jié)果寫(xiě)完之后T掉了,我就感覺(jué)我的估價(jià)函數(shù)找的不太對(duì),就去網(wǎng)上搜了大佬的博客,比這寫(xiě)了一下估價(jià)函數(shù),結(jié)果變成WA了,有點(diǎn)自閉,就去網(wǎng)上搜了搜八種方法解八數(shù)碼問(wèn)題,就選了現(xiàn)在的這個(gè),先用bfs打個(gè)表,然后就可以O(shè)(1)查詢(xún)了,省去了大量的bfs步驟,不過(guò)我在打表的時(shí)候用到了unordered_map,但是poj不讓用這個(gè)東西。。所以在poj上還是T掉了,在hdu上的以200多ms的時(shí)間A掉了,我又試了試用map交了一發(fā),在hdu上還是A了,只不過(guò)時(shí)間變成了500ms。。因?yàn)榫W(wǎng)上的正解都是用了康托展開(kāi)維護(hù)狀態(tài)的,但我不會(huì),只能用最菜的map來(lái)維護(hù)所謂的雙向哈希了,預(yù)處理bfs打個(gè)路徑表,然后直接問(wèn)什么輸出什么就可以了
代碼:
#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;//用一個(gè)cnt變量輔助維護(hù)模擬鏈表vis.clear();queue<string>q;q.push(target);//以最終狀態(tài)為起點(diǎn),bfs展開(kāi)即可,時(shí)間復(fù)雜度為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();//預(yù)處理打表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])//如果該狀態(tài)遍歷不到,則無(wú)解printf("unsolvable\n");else//如果該狀態(tài)能遍歷到,則直接輸出路徑即可{int k=vis[str];while(k!=-1){putchar(p[path[k].dir]);k=path[k].pre;}putchar('\n');}}return 0; }?
總結(jié)
以上是生活随笔為你收集整理的HDU - 1043 Eight(bfs打表)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: POJ - 2248 Addition
- 下一篇: 康托展开与逆展开(原理+模板)