標籤:
題目連結:傳送門
題意:
一個九宮格,給定你初始狀態和結束狀態,每次橫向移動和縱向移動都有一定的花費,
問從初始狀態到結束狀態的最小花費。
分析:
BFS,用優先隊列維護到達目前狀態的最優值,用hash判斷當前的狀態是否達到過。
代碼如下:
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <queue>using namespace std;const int INF = 1e9+7777;int fac[9]= {1,1,2,6,24,120,720,5040,40320}; //康托展開,用來hashstruct nod { int mp[9],pos,cost; bool operator <(const struct nod &tmp)const { return this->cost > tmp.cost; }} P;int dx[4]= {1,-1,0,0};int dy[4]= {0,0,-1,1};int s[9],e[9];int cv,ch;int vis[40320*9+100];int getHashVal(int *a) { //hash得到hash值。 int val = 0; for(int i=0; i<9; i++) { int cnt=0; for(int j=0; j<i; j++) cnt+=(a[j]>a[i]); val+=cnt*fac[i]; } return val;}bool check(nod tmp) { int cnt = 0; for(int i=0; i<9; i++) cnt+=(tmp.mp[i]==e[i]); return cnt==9;}int BFS(nod st) { priority_queue<nod> Q; Q.push(st); vis[getHashVal(st.mp)]=0; while(!Q.empty()) { nod top = Q.top(); Q.pop(); if(check(top)) { return top.cost; } for(int i=0; i<4; i++) { int tmppos = top.pos; int nowx = (top.pos/3+dx[i]+3)%3;//轉換 int nowy = top.pos%3+dy[i]; if(nowy==3){ nowy=0; nowx=(nowx+1)%3; } if(nowy==-1){ nowy=2; nowx=(nowx-1+3)%3; } swap(top.mp[nowx*3+nowy],top.mp[tmppos]); if(i<2) top.cost+=cv; else top.cost+=ch; top.pos=nowx*3+nowy; int val = getHashVal(top.mp); if(top.cost<vis[val]) { Q.push(top); vis[val]=top.cost; } swap(top.mp[nowx*3+nowy],top.mp[tmppos]); if(i<2) top.cost-=cv; else top.cost-=ch; top.pos=tmppos; } }}nod init() { nod st; for(int i=0; i<40320*9+100; i++) vis[i]=INF; for(int i=0; i<9; i++) { st.mp[i]=s[i]; if(s[i]==0) st.pos=i; } st.cost=0; return st;}int main() { while(~scanf("%d%d",&ch,&cv)) { if(cv==0&&ch==0) break; for(int i=0; i<9; i++) scanf("%d",s+i); for(int i=0; i<9; i++) scanf("%d",e+i); printf("%d\n",BFS(init())); } return 0;}/*4 96 3 08 1 24 5 76 3 08 1 24 5 731 314 3 60 1 58 2 70 3 64 1 58 2 792 41 5 34 0 78 2 61 5 04 7 38 2 612 283 4 50 2 67 1 85 7 18 6 20 3 403196312*/
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
UVALive 6665 Dragon’s Cruller (BFS + 優先隊列+hash)