1. 程式人生 > 實用技巧 >[HAOI2008]移動玩具

[HAOI2008]移動玩具

題目大意:

  給你兩個4*4的01矩陣A、B,要求你從矩陣A中將'1'移動若干步(移動即與相鄰的'0'交換位置),變換為B,輸出最小步數.

基本思路:

  本題資料較小,固定為4*4,第一時間想到狀壓(2^16),用狀壓代替hash比較容易.由於要求最小步數,bfs掃描到B矩陣即可輸出答案,複雜度遠小於dfs.

code:

  

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include
<queue> #define R register #define next exnt #define debug puts("mlg") using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; inline ll read(); inline void write(ll x); inline void writesp(ll x); inline void writeln(ll x); ll ans[65536],n,goal; bool d[5
][5]; inline ll calc(bool M[5][5]){ ll sum=0; for(R ll i=1;i<=16;i++) if(M[(i-1)/4+1][(i-1)%4+1]) sum+=1<<i-1; return sum; } queue<ll>q; inline void Bfs(ll now){ ll To; q.push(now); while(q.size()){ now=q.front();q.pop(); if(now==goal){ writeln(ans[now]);exit(
0); } for(R ll i=1;i<=16;i++) d[(i-1)/4+1][(i-1)%4+1]=(now&(1<<i-1)); for(R ll i=1;i<=4;i++){ for(R ll j=1;j<=4;j++){ if(d[i][j]){ if(i-1>0&&!d[i-1][j]){ swap(d[i-1][j],d[i][j]); To=calc(d); if(ans[To]>ans[now]+1){ ans[To]=ans[now]+1; q.push(To); } swap(d[i-1][j],d[i][j]); } if(i+1<5&&!d[i+1][j]){ swap(d[i+1][j],d[i][j]); To=calc(d); if(ans[To]>ans[now]+1){ ans[To]=ans[now]+1; q.push(To); } swap(d[i+1][j],d[i][j]); } if(j-1>0&&!d[i][j-1]){ swap(d[i][j-1],d[i][j]); To=calc(d); if(ans[To]>ans[now]+1){ ans[To]=ans[now]+1; q.push(To); } swap(d[i][j-1],d[i][j]); } if(j+1<5&&!d[i][j+1]){ swap(d[i][j+1],d[i][j]); To=calc(d); if(ans[To]>ans[now]+1){ ans[To]=ans[now]+1; q.push(To); } swap(d[i][j+1],d[i][j]); } } } } } } int main(){ for(R ll i=1,x;i<=16;i++){ char c=getchar(); while(c!='0'&&c!='1') c=getchar(); x=c-'0'; if(x) n+=1<<i-1; } memset(ans,0x3f,sizeof ans); for(R ll i=1,x;i<=16;i++){ char c=getchar(); while(c!='0'&&c!='1') c=getchar(); x=c-'0'; if(x) goal+=1<<i-1; } ans[n]=0; Bfs(n); } inline ll read(){ ll x=0,t=1;char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') t=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*t; } inline void write(ll x){ if(x<0){putchar('-');x=-x;} if(x<=9){putchar(x+'0');return;} write(x/10);putchar(x%10+'0'); } inline void writesp(ll x){ write(x);putchar(' '); } inline void writeln(ll x){ write(x);putchar('\n'); }