您的位置:首页 > 其它

HDU1254推箱子(AC)

2016-09-27 15:42 190 查看
推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动.

现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.



[align=left]Input[/align]
输入数据的第一行是一个整数T(1<=T<=20),代表测试数据的数量.然后是T组测试数据,每组测试数据的第一行是两个正整数M,N(2<=M,N<=7),代表房间的大小,然后是一个M行N列的矩阵,代表房间的布局,其中0代表空的地板,1代表墙,2代表箱子的起始位置,3代表箱子要被推去的位置,4代表搬运工的起始位置.

[align=left]Output[/align]
对于每组测试数据,输出搬运工最少需要推动箱子多少格才能帮箱子推到指定位置,如果不能推到指定位置则输出-1.

[align=left]Sample Input[/align]

1
5 5
0 3 0 0 0
1 0 1 4 0
0 0 1 0 0
1 0 2 0 0
0 0 0 0 0


[align=left]Sample Output[/align]

4
[code]#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

//AC

//BFS+BFS

//第一次提交WA,找找错在哪儿?如果箱子被推到一面墙上,那么箱子只能沿着墙移动这边,但是我已经控制住了,左右都动不了的
//问题还在于要确认人的位置能否到箱子的四周,这个也要确定的啊,第一次做没有确定

//第2次修改还是WA,已经加上对人的判断了,还是不对,网上搜了下有人说用DFS+BFS,但是自己的方法是BFS+BFS,我还是倾向于用BFS,这样代码好写些,DFS当然也是要练习的
//我把人和箱子的状态只走一遍应该是对的,是对的,但是要注意那个人的位置应该是原始箱子的位置
//自己第二次提交还是WA的原因后来走查代码看了好多遍终于发现ans没有Init,ans=-1要写,要不然后面如果有-1的根本就还是上一次的值就不对了
//AC

#define MAX 10

int M = 0;
int N = 0;
int ans = -1;

int startx = 0;
int starty = 0;
int px = 0;
int py = 0;
int endx = 0;
int endy = 0;

int map[MAX][MAX];
//int visit[MAX][MAX];

typedef struct node
{
int px;  //人站的位置
int py;
int x;   //箱子站的位置
int y;
int step;
}nodes;

typedef struct ppp
{
int x;
int y;
}ppps;

nodes que[MAX*MAX];
ppps person[MAX*MAX];

int dir[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, {0,1} };
int visit[MAX][MAX][MAX][MAX];
int visitperson[MAX][MAX];

void init()
{
int j = 0;
int m = 0;
int n = 0;
int k = 0;
int i = 0;
for (j = 0; j < MAX; j++)
{
for (m = 0; m < MAX; m++)
{
map[j][m]   = 0;
que
.px   = 0;
que
.py   = 0;
que
.x    = 0;
que
.y    = 0;
que
.step = 0;
visitperson[j][m] = 0;
person
.x = 0;
person
.y = 0;
n += 1;

for (k = 0; k < MAX; k++)
{
for (i = 0; i < MAX; i++)
{
visit[j][m][k][i] = 0;
}
}
}
}
startx = 0;
starty = 0;
px = 0;
py = 0;
endx = 0;
endy = 0;
ans = -1;
return;
}

void initperson()
{
int j = 0;
int m = 0;
int n = 0;
for (j = 0; j < MAX; j++)
{
for (m = 0; m < MAX; m++)
{

visitperson[j][m] = 0;
person
.x = 0;
person
.y = 0;
n += 1;
}
}
return;
}

//人的位置能否走到
int bfsperson(int startx, int starty, int enddx, int enddy,int boxx,int boxy)
{
initperson();
int front = 0;
int back = 0;
int tmpx = 0;
int tmpy = 0;
int i = 0;
person[back].x   = startx;
person[back++].y = starty;

visitperson[startx][starty] = 1;
while (front<back)
{
if ((enddx == person[front].x) && (enddy == person[front].y))
{
return 1;
}
for (i = 0; i < 4;i++)
{
tmpx = person[front].x + dir[i][0];
tmpy = person[front].y + dir[i][1];
if (((tmpx<1) || (tmpx>M)) || ((tmpy<1) || (tmpy>N))) continue;
if (1 == map[tmpx][tmpy]) continue; //墙不能走
if ((tmpx == boxx) && (tmpy == boxy)) continue; //箱子不能走
//if ((tmpx == enddx) && (tmpy == enddy)) continue; //箱子不能走
if (1 == visitperson[tmpx][tmpy]) continue; //访问过不能走
person[back].x   = tmpx;
person[back++].y = tmpy;
visitperson[tmpx][tmpy] = 1;
}
front += 1;
}
return 0;
}

//箱子的位置能否走到
void bfs(int x, int y)
{
int front = 0;
int back    = 0;
int i       = 0;
int tmpx    = 0;
int tmpy    = 0;
int tmpboxx = 0;
int tmpboxy = 0;

//人和箱子一开始是不在一起的,人要先到箱子的周围吧,但是是问箱子要退多少格,那人的初始位置在哪儿貌似不重要啊
que[back].px     = px;
que[back].py     = py;
que[back].x      = startx;
que[back].y      = starty;
que[back++].step = 0;
//visit[px][py][startx][starty] = 1;

while (front < back)
{
if ((endx == que[front].x) && (endy == que[front].y))
{
ans = que[front].step;
return;
}

if (((1 == que[front].x) && (1 == que[front].y)) || ((1 == que[front].x) && (N == que[front].y)) || ((M == que[front].x) && (1 == que[front].y)) || ((M == que[front].x) && (N == que[front].y)))
{
front += 1;
continue;
}

for (i = 0; i < 4;i++)
{
tmpx = que[front].x + dir[i][0]; //箱子周围的位置也就是人站的位置
tmpy = que[front].y + dir[i][1];
if (((tmpx<1) || (tmpx>M)) || ((tmpy<1) || (tmpy>N))) continue;
if (1 == map[tmpx][tmpy]) continue; //墙不能走
if (0 == bfsperson(que[front].px, que[front].py, tmpx, tmpy, que[front].x, que[front].y)) continue; //人是否到达这个位置

//人在箱子的下面
if ((1 == (tmpx - que[front].x)) && (tmpy == que[front].y))
{
tmpboxx = que[front].x - 1;
tmpboxy = que[front].y;
if (((tmpboxx<1) || (tmpboxx>M)) || ((tmpboxy<1) || (tmpboxy>N))) continue;
//if (((1 == tmpboxx) && (1 == tmpboxy)) || ((1 == tmpboxx) && (N == tmpboxy)) || ((M == tmpboxx) && (1 == tmpboxy)) || ((M == tmpboxx) && (N == tmpboxy))) continue;
if (1 == map[tmpboxx][tmpboxy]) continue; //墙不能走

if (1 == visit[que[front].x][que[front].y][tmpboxx][tmpboxy]) continue;

que[back].px = que[front].x; //这是个问题,这边的位置不对,人站的地方应该是箱子在的地方了,而不是应该写成tmpx,这个就不对了que[back].px = tmpx;,不对
que[back].py = que[front].y;
que[back].x  = tmpboxx;
que[back].y  = tmpboxy;
que[back++].step = que[front].step+1;
visit[que[front].x][que[front].y][tmpboxx][tmpboxy] = 1;
}
//人在箱子的上面
if ((1 == (que[front].x - tmpx)) && (tmpy == que[front].y))
{
tmpboxx = que[front].x + 1;
tmpboxy = que[front].y;
if (((tmpboxx<1) || (tmpboxx>M)) || ((tmpboxy<1) || (tmpboxy>N))) continue;
//if (((1 == tmpboxx) && (1 == tmpboxy)) || ((1 == tmpboxx) && (N == tmpboxy)) || ((M == tmpboxx) && (1 == tmpboxy)) || ((M == tmpboxx) && (N == tmpboxy))) continue;
if (1 == map[tmpboxx][tmpboxy]) continue; //墙不能走

if (1 == visit[que[front].x][que[front].y][tmpboxx][tmpboxy]) continue;

que[back].px = que[front].x;
que[back].py = que[front].y;
que[back].x = tmpboxx;
que[back].y = tmpboxy;
que[back++].step = que[front].step + 1;
visit[que[front].x][que[front].y][tmpboxx][tmpboxy] = 1;
}

//人在箱子的左边
if ((que[front].x == tmpx) && (1 == (que[front].y - tmpy)))
{
tmpboxx = que[front].x ;
tmpboxy = que[front].y +1;
if (((tmpboxx<1) || (tmpboxx>M)) || ((tmpboxy<1) || (tmpboxy>N))) continue;
//if (((1 == tmpboxx) && (1 == tmpboxy)) || ((1 == tmpboxx) && (N == tmpboxy)) || ((M == tmpboxx) && (1 == tmpboxy)) || ((M == tmpboxx) && (N == tmpboxy))) continue;
if (1 == map[tmpboxx][tmpboxy]) continue; //墙不能走

if (1 == visit[que[front].x][que[front].y][tmpboxx][tmpboxy]) continue;

que[back].px = que[front].x;
que[back].py = que[front].y;
que[back].x = tmpboxx;
que[back].y = tmpboxy;
que[back++].step = que[front].step + 1;
visit[que[front].x][que[front].y][tmpboxx][tmpboxy] = 1;
}

//人在箱子的右边
if ((que[front].x == tmpx) && (1 == (tmpy - que[front].y)))
{
tmpboxx = que[front].x;
tmpboxy = que[front].y - 1;
if (((tmpboxx<1) || (tmpboxx>M)) || ((tmpboxy<1) ||  (tmpboxy>N)))continue;
if (1 == map[tmpboxx][tmpboxy]) continue;
//if (((1 == tmpboxx) && (1 == tmpboxy)) || ((1 == tmpboxx) && (N == tmpboxy)) || ((M == tmpboxx) && (1 == tmpboxy)) || ((M == tmpboxx) && (N == tmpboxy))) continue;

if (1 == visit[que[front].x][que[front].y][tmpboxx][tmpboxy])continue;

que[back].px = que[front].x;
que[back].py = que[front].y;
que[back].x = tmpboxx;
que[back].y = tmpboxy;
que[back++].step = que[front].step + 1;
visit[que[front].x][que[front].y][tmpboxx][tmpboxy] = 1;
}
}
front += 1;
}
return;
}

int main()
{
int T = 0;
int i = 0;
int j = 0;
int m = 0;
freopen("input.txt","r",stdin);
scanf("%d", &T);
for (i = 0; i < T;i++)
{
init();
scanf("%d %d", &M, &N);
for (j = 1; j <= M; j++)
{
for (m = 1; m <= N; m++)
{
scanf("%d",&map[j][m]);
if (2 == map[j][m])
{
startx = j;
starty = m;
}

if (3 == map[j][m])
{
endx = j;
endy = m;
}

if (4 == map[j][m])
{
px = j;
py = m;
}
}
//只能推,不能拉
}

if (((1 == startx) && (1 == starty)) || ((1 == startx) && (N == starty)) || ((M == startx) && (1 == starty)) || ((M == startx) && (N == starty)))
{
if ((startx != endx) || (starty != endy))
{
printf("-1\n");
}
}

bfs(startx, starty);
printf("%d\n",ans);
}
return 0;

}


[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: