HDOJ 1254 推箱子(bfs+dfs)

题目连接:ヽ(ˋ▽ˊ)ノ


思路:每个点不止可以走一次, 而是可以可以从不同的方向到达一次,(wa了n多次)


code:

#include <stdio.h>
#include <string.h>
typedef struct
{
    int x, y, count;
    int xx, yy;
}node;
node step, quene[1000];
int map[10][10], used[4][10][10], visited[10][10];//用第三维标记方向
int m = 0, n = 0, X1 = 0, Y1 = 0, X2 = 0, Y2 = 0, flag1 = 0, flag2 = 0;//用flag1表明人能不能到箱子后面,flag2表明要走的步数
int dir[4][2] = {{-1, 0}, {0, 1}, {0, -1}, {1,0 }};
void dfs(int x, int y)
{
    int i = 0, fx = 0, fy = 0;
    if(x == X2 && y == Y2)
        flag1 = 1;
    if(flag1)
        return;
    for(i = 0; i<4; i++)
    {
        fx = x+dir[i][0]; fy = y+dir[i][1];
        if(map[fx][fy] != 1 && !visited[fx][fy] && fx>-1 && fx<m+2 && fy>-1 && fy<n+2)
        {
            visited[fx][fy] = 1;
            dfs(fx, fy);
        }
    }
}
void bfs()
{
    int i = 0, x = 0, y = 0, fx = 0, fy = 0, count = 0, front = 0, rear = 0;
    quene[rear++] = step;
    while(front<rear)
    {
        x = quene[front].x; y = quene[front].y;
        count = quene[front].count;
        X1 = quene[front].xx; Y1 = quene[front++].yy;//改变人的位置
        for(i = 0; i<4; i++)
        {
            flag1 = 0;
            fx = x+dir[i][0]; fy = y+dir[i][1];//从x y推到fx fy
            if(used[i][fx][fy]) continue;//下一个位置从这方向走过 不能再走
            if(used[i][x][y])//表明当前点是从i方向推过来的 于是人一定在x y后面 可以向fx fy前进
            {
            	flag1 = 1;
            }
            else
            {
				if(map[x+dir[3-i][0]][y+dir[3-i][1]] != 1)//3-i为当前方向i的相反方向 具体看dir数组
				{
					X2 = x+dir[3-i][0]; Y2 = y+dir[3-i][1];//当前箱子的反方向
					visited[x][y] = 1;//箱子在的位置人不能走 标记
					dfs(X1, Y1);//X1 Y1 人开始的点  X2 Y2 到达的点
					memset(visited, 0, sizeof(visited));
				}
            }
			if(flag1 && map[fx][fy] != 1)//如果人能到达该箱子后面和前进的点可走
			{
				step.x = fx; step.y = fy; step.count = count+1;
				step.xx = x; step.yy = y;
				used[i][fx][fy] = 1;
				quene[rear++] = step;
			}
            if(flag1 && map[fx][fy] == 3)
            {
                flag2 = count+1;
                return;
            }
        }
    }
}
int main()
{
    int i = 0, j = 0, t = 0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&m,&n);
        for(i = 0; i<m+2; i++)
        {
            for(j = 0; j<n+2; j++)
            {
                if(i == 0 || j == 0 || i == m+1 || j == n+1)
                    map[i][j] = 1;
                else
                {
                    scanf("%d",&map[i][j]);
                    if(map[i][j] == 4)
                    {
                        step.xx = i; step.yy = j;
                    }
                    if(map[i][j] == 2)
                    {
                        step.x = i; step.y = j; step.count = 0;
                    }
                }
            }
        }
        memset(used, 0, sizeof(used));
        flag2 = 0;
        bfs();
        if(flag2)
            printf("%d\n",flag2);
        else
            printf("-1\n");
    }
    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值