问题 A: [HAOI2008]移动玩具
时间限制: 1 Sec 内存限制: 162 MB提交: 54 解决: 38
[ 提交][ 状态][ 讨论版]
题目描述
在一个4*4的方框内摆放了若干个相同的玩具,某人想将这些玩具重新摆放成为他心中理想的状态,规定移动
时只能将玩具向上下左右四个方向移动,并且移动的位置不能有玩具,请你用最少的移动次数将初始的玩具状态移
动到某人心中的目标状态。
输入
前4行表示玩具的初始状态,每行4个数字1或0,1表示方格中放置了玩具,0表示没有放置玩具。接着是一个空
行。接下来4行表示玩具的目标状态,每行4个数字1或0,意义同上。
输出
一个整数,所需要的最少移动次数。
样例输入
1111
0000
1110
0010
1010
0101
1010
0101
样例输出
4
[HAOI2008]移动玩具
额,装个逼,水题。
考试的时候看到数据范围就想到了状压,但二维状压也不会啊……于是乎发现压16位也是可以的,于是乎神来之笔的压了16位,向上向下就是(1<<(i±4)),向左向右就是(1<<(i±1)),注意判断边界即可,简单的证明了一下宽搜的正确性后打了出来,A了……好吧确实少了点,不过就是这样,乱搞压正解。
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#define V 505
using
namespace
std;
char
s[5][5],t[5][5];
bool
vis[50];
int
f[5][5],w[5][5],id,is;
int
ans=V*V;
struct
data
{
int
to,next,dis;
}Edge[2*V];
int
head[V],dep[V],sd[V],tot;
inline
void
add1(
int
x,
int
y,
int
z)
{
Edge[tot].to=y;
Edge[tot].dis=z;
Edge[tot].next=head[x];
head[x]=tot++;
}
void
dfs(
int
x,
int
num)
{
// cout<<x
if
(x==id)
{
for
(
int
i=head[x];i!=-1;i=Edge[i].next)
{
if
(!vis[Edge[i].to])
{
ans=min(ans,num+Edge[i].dis);
return
;
}
}
}
else
{
for
(
int
i=head[x];i!=-1;i=Edge[i].next)
{
if
(!vis[Edge[i].to])
{
vis[Edge[i].to]=1;
dfs(x+1,num+Edge[i].dis);
vis[Edge[i].to]=0;
}
}
}
}
int
main()
{
// freopen("in.txt","r",stdin); freopen("out.txt","w",stdout);
// freopen("movea.in","r",stdin); freopen("movea.out","w",stdout);
memset
(head,-1,
sizeof
(head));
for
(
int
i=1;i<=4;i++)
for
(
int
j=1;j<=4;j++)
cin>>s[i][j];
getchar
();
for
(
int
i=1;i<=4;i++)
for
(
int
j=1;j<=4;j++)
{
cin>>t[i][j];
if
(s[i][j]==t[i][j])
s[i][j]=t[i][j]=
'0'
;
}
for
(
int
i=1;i<=4;i++)
for
(
int
j=1;j<=4;j++)
{
if
(s[i][j]==
'1'
)
f[i][j]=++id;
if
(t[i][j]==
'1'
)
w[i][j]=++is;
}
// return 0;
int
dis;
for
(
int
i=1;i<=4;i++)
for
(
int
j=1;j<=4;j++)
if
(s[i][j]==
'1'
)
{
for
(
int
x=1;x<=4;x++)
for
(
int
y=1;y<=4;y++)
if
(t[x][y]==
'1'
)
{
dis=
abs
(x-i)+
abs
(y-j);
add1(f[i][j],w[x][y],dis);
//cout<<i<<" % "<<j<<endl;
//cout<<x<<" !"<<y<<endl;
}
}
dfs(1,0);
if
(ans==V*V)
cout<<0;
else
cout<<ans<<endl;
return
0;
}