Aizu0121
題意
t(<1000)組數據
0可以和上下左右四個位置交換
求最少多少步能變成圖d這種情況
思路
BFS求最短路徑
難點
正難則反:以往我BFS都是正着求,從輸入狀態到達理想狀態,然而這道題這麼做卻很麻煩,我們應該考慮從理想狀態到達輸入狀態,這完全不影響結果,反而有利於我們求解。
利用數據結構:這裏的輸入量很大,每次求一次BFS很麻煩,這種情況考慮BFS求所有情況,然後保存到map當中,直接輸出結果。
選用合理數據類型保存:我思考了很久該如何去保存這樣的數組,看到別人的解法是用string來表示整個數組的狀態,實在是秒。
新遇到的stl函數:
getline(cin,str)可以接收一行string類型(包括空格) 所在庫<string>
s.erase(remove(s.begin(), s.end(), theCharacterNeedtoRemove), s.end()); 所在庫<algorithm>
上面這句話remove函數將string中第三個參數位置的字符移動到最後面,最後返回了去掉第三個參數的字符串的end()迭代器,利用他的返回值結合erase刪除特定字符。
remove()函數的複雜度O(26 * n) = O(n)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll maxn = 1e6 + 5;
const int N = 10;
int a[N];
string s="01234567";
map<string,int>mp;
int dx[4]={1,-1,4,-4};
void bfs(){
queue<string>q;
q.push(s);
while(!q.empty()){
string p=q.front();
q.pop();
int pos=p.find('0');
for(int i=0;i<4;i++){
int tpos=pos+dx[i];
if(tpos>=0 && tpos<=7 && (!((pos==3)&&i==0)) && (!((pos==4)&&i==1))){
string k=p;
swap(k[pos],k[tpos]);
if(mp[k]==0 && k!="01234567"){
mp[k]=mp[p]+1;
q.push(k);
}
}
}
}
}
int main(){
bfs();
while(getline(cin,s)){
s.erase(remove(s.begin(),s.end(),' '),s.end());
printf("%d\n",mp[s]);
}
return 0;
}