hdu 1254 推箱子 广搜+ 深搜

5 篇文章 0 订阅

http://acm.hdu.edu.cn/showproblem.php?pid=1254

 

注意以下几点

1.  箱子是否可走

2. 人是否可达箱子后面

3. 箱子的每个方向只走一次,而不是每个位置

 

广搜箱子路径,深搜人可否达箱子后面, 记录方向用visb[10][10][4]来记录

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
int a[10][10], m, n, sx, sy, px, py, visb[10][10][4], visp[10][10], flag;
int mov[4][2]= {1, 0, 0, 1, -1, 0, 0, -1};
struct node{
    int x, y, px, py, step;
};
void init(){
    int i, j;
    scanf("%d%d", &m, &n);
    for( i=0; i<m; i++)
        for( j=0; j<n; j++){
            scanf("%d", &a[i][j]);
            if( a[i][j]==2) sx= i, sy= j;
            if( a[i][j]==4) px= i, py= j;
        }
    memset( visb, 0, sizeof( visb));
}
bool check(int x, int y){
    if( x>=0 && x<m && y>=0 && y<n && a[x][y]!= 1) return true;
    return false;
}
bool dfs(int dx, int dy, node temp){
    if( flag )return true;
    int i, j;
    node next;
    if( dx== temp.px && temp.py== dy) {
        flag= 1;
        return true;
    }
    next.x= temp.x, next.y=temp.y;
    for( i=0; i<4; i++){
        next.px= temp.px + mov[i][0];
        next.py= temp.py + mov[i][1];
        //注意搜索人是否可达箱子后面时,不仅不可走1位置,也不能走箱子目前的位置
        if( check( next.px, next.py) && !visp[next.px][next.py] && !( next.px == temp.x && next.py== temp.y)){
            visp[ next.px][next.py]= 1;
            if( dfs( dx, dy, next) ) return true;
            visp[next.px][next.py]= 0; //回溯不要写在else里……………………
        }
    }
    return false;
}
void bfs(){
    int i, j, k, rx, ry;
    queue<node >q;
    node start, next, head;
    start.px= px, start.py= py;
    start.x= sx, start.y= sy;
    start.step= 0;
    q.push( start );
    while( !q.empty()){
        head= q.front();
        q.pop();
        if( a[head.x][head.y]== 3){
            printf("%d\n", head.step);
            return;
        }
        //cout<<head.x<<" "<<head.y<<endl;
        for( i=0; i<4; i++){
            next.x= head.x+mov[i][0];  //箱子的目的地址
            next.y= head.y+mov[i][1];
            next.px= head.x;  //推箱子后人的位置为箱子所在位置
            next.py= head.y;
            next.step= head.step + 1;
            rx= head.x- mov[i][0];  //箱子后面,人推箱子时所站的位置
            ry= head.y- mov[i][1];
            if( check( next.x, next.y ) && !visb[next.x][next.y][i] && check( rx, ry)){
                memset( visp, 0, sizeof( visp));
                visp[head.px][head.py]= 1;
                flag= 0;
                if( dfs( rx, ry, head) ){  //看人是否可达箱子后面
                    visb[ next.x][next.y][i]= 1;
                    q.push( next);
                    //cout<<next.x<<" "<<next.y<<" "<<next.px<<" "<<next.py<<endl;
                }

            }
        }
    }
    printf("-1\n");
}
int main(){
  //  freopen("1.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while( T--){
        init();
        bfs();
    }
    return 0;
}

 第一次深搜时,搜索到了忘记return了……效率好低
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值