HDU 1254 推箱子 bfs

C++:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
//0空位 1墙 2起点 3终点 4人的起点

int m,n;
int graph[10][10],vis[10][10][10][10];
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};

struct Point{
    int x,y;
    int x_box,y_box,step; //箱子及其已经使用够的步数
}p;

int bfs(){
    Point cur,next;
    queue<Point> q;
    q.push(p);
    int res = INF;
    vis[p.x][p.y][p.x_box][p.y_box] = true;  //初值为INF
    while(!q.empty()){
        cur = q.front();
        q.pop();
        if(graph[cur.x_box][cur.y_box]==3){  //箱子达到了终点
            res = min(res,cur.step);
        }
        
        for(int i=0;i<4;i++){
            next = cur;
            next.x += dx[i];
            next.y += dy[i];   //推箱子,移动的是人
            if(next.x>=0 && next.x<m && next.y>=0 && next.y<n && graph[next.x][next.y]!=1 && next.step<vis[next.x][next.y][next.x_box][next.y_box]){  //判断人的位置是否合法
                if(next.x==next.x_box && next.y==next.y_box){
                    next.x_box += dx[i];
                    next.y_box += dy[i];
                    next.step++;
                    if(next.x_box>=0 && next.x_box<m && next.y_box>=0 && next.y_box<n && graph[next.x_box][next.y_box]!=1 && next.step<vis[next.x][next.y][next.x_box][next.y_box]){
                        vis[next.x][next.y][next.x_box][next.y_box] = next.step;
                        q.push(next);
                    }
                }
                else{
                    vis[next.x][next.y][next.x_box][next.y_box] = next.step;
                    q.push(next);   //此时箱子没动,不需要更新箱子的step,直接入队
                }
            }
        }
    }
    return res;
}

int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        memset(vis,INF,sizeof(vis));
        scanf("%d%d",&m,&n);
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++){
                scanf("%d",&graph[i][j]);
                if(graph[i][j]==4){  //人的起点
                    p.x = i;
                    p.y = j;
                    p.step = 0;
                }
                else if(graph[i][j]==2){
                    p.x_box = i;
                    p.y_box = j;
                }
            }
        int res = bfs();
        if(res==INF)
            res = -1;
        printf("%d\n",res);
    }
    return 0;
}

JAVA:

import java.util.*;

//0空格 1墙 2箱子起点 3箱子终点 4人起点
public class HDU1254 {
	public static class Point{
		public int x,y,x_box,y_box,step;
		Point(){
			
		}
		Point(Point p){
			x = p.x;
			y = p.y;
			x_box = p.x_box;
			y_box = p.y_box;
			step = p.step;
		}
	}
	public static int[] dx = {0,0,1,-1};
	public static int[] dy = {1,-1,0,0};
	public static int INF = 0x3f3f3f3f;
	public static int m,n;
	public static int[][] graph;
	public static int[][][][] vis;
	public static Point p0;
	public static int bfs() {
		int res = Integer.MAX_VALUE;
		Point cur,next;
		Queue<Point> q = new LinkedList<>();
		vis[p0.x][p0.y][p0.x_box][p0.y_box] = 1;
		q.offer(p0);
		while(!q.isEmpty()) {
			cur = q.poll();
			if(graph[cur.x_box][cur.y_box]==3) {
				res = Math.min(res, cur.step);  //判断箱子是否到达了终点
			}
			for(int i=0;i<4;i++) {  //移动人的位置
				next = new Point(cur);
				next.x += dx[i];
				next.y += dy[i];
				if(next.x>=0 && next.x<m && next.y>=0 && next.y<n && graph[next.x][next.y]!=1 &&
						next.step<vis[next.x][next.y][next.x_box][next.y_box]) {
					if(next.x==next.x_box && next.y==next.y_box) {
						//人走到箱子的位置上了,重合了。重合之后,箱子能推动,才能表示一个新的状态
						next.x_box += dx[i];
						next.y_box += dy[i];
						next.step++;
						if(next.x_box>=0 && next.x_box<m && next.y_box>=0 && next.y_box<n 
								&& graph[next.x_box][next.y_box]!=1 
								&& next.step<vis[next.x][next.y][next.x_box][next.y_box]) {
							vis[next.x][next.y][next.x_box][next.y_box] = next.step;
							q.offer(next);
						}
					}
					else {
						vis[next.x][next.y][next.x_box][next.y_box] = next.step;
						q.offer(next);
					}
				}
			}
		}
		return res;
	}
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int T = sc.nextInt();
		while(T-->0) {
			m = sc.nextInt();
			n = sc.nextInt();
			graph = new int[10][10];
			vis = new int[10][10][10][10];
//			Arrays.fill(vis, Integer.MAX_VALUE);
			for(int i=0;i<10;i++)
				for(int j=0;j<10;j++)
					for(int k=0;k<10;k++)
						for(int l=0;l<10;l++)
							vis[i][j][k][l] = Integer.MAX_VALUE;
			p0 = new Point();
			for(int i=0;i<m;i++)
				for(int j=0;j<n;j++) {
					graph[i][j] = sc.nextInt();
					if(graph[i][j]==4) {
						p0.x = i;
						p0.y = j;
						p0.step = 0;
					}
					else if(graph[i][j]==2) {
						p0.x_box = i;
						p0.y_box = j;
					}
				}
			int res = bfs();
			if(res==Integer.MAX_VALUE)
				res = -1;
			System.out.println(res);
		}
	}
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值