1. 程式人生 > >第十場 hdu 6171 Admiral(雙向bfs找交點)

第十場 hdu 6171 Admiral(雙向bfs找交點)

pos 交換 size php log print 如果 雙向 dmi

http://acm.hdu.edu.cn/showproblem.php?pid=6171

題目大意:給你一個塔形的數據共有1個0、2個1、3個2、4個3、5個4、6個5.你能夠把0這個數據和它的上、左上、下、右下的數據進行交換。問在最多20步內能否變成按順序排列的塔形數據?如果能輸出最小步數,否則輸出-1.

解題思路:因為有20步4個方向所以暴力搜索肯定是不可以的。因為有起點有終點所以我們能分兩部分去搜索。但是這樣搜索的話還是要去找枚舉相遇的,這樣的話還是會超時的,所以我們在搜索的同時還要找出來一下相遇的最少步數。
我們應該用隊列去完成寬搜並用map去存儲到達該狀態的最少步數,並且起點和終點狀態最多只能向前枚舉10次以減少時間復雜度。如果在某個狀態枚舉的情況相遇了則說明已經找到了最少的步數。
我們應該對給出的狀態是不是起點狀態進行特判,找到最少步數為0的情況。

AC代碼:

技術分享
  1 #include <iostream>
  2 #include<bits/stdc++.h>
  3 //if(~i)//當i不是-1時滿足條件
  4 using namespace std;
  5 queue<string>que;
  6 map<string,int>mp;
  7 int up[]= {-1,0,-1,1,2,-1,3,4,5,-1,6,7,8,9,-1,10,11,12,13,14,-1};
  8 int upleft[]= {-1,-1,0,-1,1,2,-1,3,4,5,-1,6,7,8,9,-1
,10,11,12,13,14}; 9 int down[]= {1,3,4,6,7,8,10,11,12,13,15,16,17,18,19,-1,-1,-1,-1,-1,-1}; 10 int downright[]= {2,4,5,7,8,9,11,12,13,14,16,17,18,19,20,-1,-1,-1,-1,-1,-1}; 11 string ori="011222333344444555555"; 12 13 int solve(string next,string now,int nextpos,int pos) 14 { 15 if(~nextpos)
16 { 17 swap(next[pos],next[nextpos]); 18 next[21]=nextpos/10+0; 19 next[22]=nextpos%10+0; 20 int cnt1=mp[next]; 21 int cnt2=mp[now]; 22 if(!cnt1) 23 { 24 mp[next]=mp[now]+1; 25 que.push(next); 26 } 27 else if((cnt1>=20&&cnt2<=11)||(cnt2>=20&&cnt1<=11)) 28 return cnt1+cnt2-20; 29 swap(next[pos],next[nextpos]); 30 } 31 return 0; 32 } 33 int dfs(string s) 34 { 35 int index; 36 while(!que.empty()) 37 que.pop(); 38 mp.clear(); 39 for(int i=0; i<21; i++) 40 { 41 if(s[i]==0) 42 { 43 index=i; 44 break; 45 } 46 } 47 char st[5]; 48 st[0]=index/10+0; 49 st[1]=index%10+0; 50 st[2]=\0; 51 que.push(s+st); 52 que.push(ori+"00"); 53 mp[s+st]=20; 54 mp[ori+"00"]=1; 55 while(!que.empty()) 56 { 57 string now=que.front(); 58 que.pop(); 59 int num=mp[now]; 60 if(num==11||num==30) 61 continue; 62 int pos=(now[21]-0)*10+(now[22]-0); 63 int nextpos=up[pos]; 64 string next=now; 65 int ans=solve(next,now,nextpos,pos); 66 if(ans) 67 return ans; 68 nextpos=upleft[pos]; 69 ans=solve(next,now,nextpos,pos); 70 if(ans) 71 return ans; 72 nextpos=down[pos]; 73 ans=solve(next,now,nextpos,pos); 74 if(ans) 75 return ans; 76 nextpos=downright[pos]; 77 ans=solve(next,now,nextpos,pos); 78 if(ans) 79 return ans; 80 } 81 return -1; 82 } 83 int main() 84 { 85 int t; 86 //freopen("1001.in","r",stdin); 87 scanf("%d",&t); 88 while(t--) 89 { 90 string s="",st; 91 for(int i=0; i<21; i++) 92 { 93 cin>>st; 94 s+=st; 95 } 96 if(s==ori) 97 { 98 printf("0\n"); 99 continue; 100 } 101 int ans=dfs(s); 102 if(ans==-1) 103 printf("too difficult\n"); 104 else 105 printf("%d\n",ans); 106 } 107 return 0; 108 }
View Code

第十場 hdu 6171 Admiral(雙向bfs找交點)