[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(‘ ‘); }