[BZOJ1054/Luogu4289][HAOI2008]移動玩具
阿新 • • 發佈:2018-12-23
題目連結:
日常水題
因為總共\(16\)個節點,用二進位制表示每一個狀態,跑一遍最短路即可。
因為邊權都是\(1\),直接\(BFS\)即可。
時間複雜度 \(O(2^{16}*16*4)=AC\)
#include <queue> #include <cstdio> #include <cstring> int St,Ed,Dis[1<<16]; char s[5]; void BFS() { if(St==Ed)return; std::queue<int> q; memset(Dis,0x3f,sizeof Dis); q.push(St),Dis[St]=0; for(int x;!q.empty();) { x=q.front(),q.pop(); for(int i=0;i<16;++i) { int wx; if(i<12&&(x>>i&1)!=(x>>(i+4)&1))//不是第一行,且狀態與上方不同 { wx=x^(1<<i)^(1<<(i+4));//交換兩位 if(Dis[wx]>Dis[x]+1) { Dis[wx]=Dis[x]+1; if(wx==Ed)return; q.push(wx); } }//向上 if(i>3&&(x>>i&1)!=(x>>(i-4)&1)) { wx=x^(1<<i)^(1<<(i-4)); if(Dis[wx]>Dis[x]+1) { Dis[wx]=Dis[x]+1; if(wx==Ed)return; q.push(wx); } }//向下 if(i%4!=3&&(x>>i&1)!=(x>>(i+1)&1)) { wx=x^(1<<i)^(1<<(i+1)); if(Dis[wx]>Dis[x]+1) { Dis[wx]=Dis[x]+1; if(wx==Ed)return; q.push(wx); } }//向左 if(i%4&&(x>>i&1)!=(x>>(i-1)&1)) { wx=x^(1<<i)^(1<<(i-1)); if(Dis[wx]>Dis[x]+1) { Dis[wx]=Dis[x]+1; if(wx==Ed)return; q.push(wx); } }//向右 } } } int main() { for(int i=0;i<4;++i) { scanf("%s",s); for(int j=0;j<4;++j) St=St<<1|(s[j]&1); } for(int i=0;i<4;++i) { scanf("%s",s); for(int j=0;j<4;++j) Ed=Ed<<1|(s[j]&1); } BFS(); printf("%d\n",Dis[Ed]); return 0; }