hdu1254推箱子

今天是我第一次在这里写解题报告,我还是小菜鸟,请大家多多指教

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1254

我的思路:用广搜找箱子的移动路径,由于考虑到人必须能推的了,所以在每次移动的时候要确定人能够到达推箱子的地方,所以,广搜的同时用深搜确定人的位置。但是在调试过程中发现人的位置用广搜的速度更快,所以最后改成了广搜,提交失败了好几次,总结原因:
一、一开始没有记录一个点走过多少次,导致重复搜索,死循环超时

二、在广搜箱子的同时没有更新人的位置,导致某些数据wa

三、因为考虑到箱子有可能要往回推,所以在去重时犹豫不决,最后用了一个数组,限制每个点最多走3次

四、特殊数据:

400000

020000

000000

000011

000013

来个20组,搜的够呛,所以加了个补丁

另外还有特殊数据

000400

000300

111211

000000

000000

------------------

#include <iostream>
#include <cstdio>
#include <queue>
#include<cstring>
using namespace std;
char map[33][33];
struct node
{
    int bx,by,rx,ry,num;//变量含义:箱子x,箱子y,人x,人y,步数
};
queue<node> q;//箱子路径的广搜
queue<node> rq;//人的位置的广搜
node m[5];
int x,y;
bool mark[33][33];
char mrk[33][33];//这个数组是用来记录一个点被走过几次,为了避免搜索时重复走以前的路,不过。。我自己感觉都不明白。。
bool bfs(int rx,int ry,int ex,int ey);
void r_next();
bool dfs(int rx,int ry,int ex,int ey)//人的位置的深搜
{
    int i;
    if(rx==ex&&ry==ey)
        return true;
    for(i=1;i<=4;i++)
    {
        if(map[rx+m[i].bx][ry+m[i].by]=='0'&&map[rx+m[i].bx][ry+m[i].by]!='r')
        {
            map[rx][ry]='r';
            if(dfs(rx+m[i].bx,ry+m[i].by,ex,ey))
            {
                map[rx][ry]='0';
                return true;
            }
            map[rx][ry]='0';
        }
    }
    return false;
}
void next()//用来确定下一步
{
    int i;
    node temp=q.front();
    for(i=1;i<=4;i++)
    {
        temp.num=q.front().num+1;
        temp.bx=q.front().bx+m[i].bx;
        if(temp.bx<1||temp.bx>x)
            continue;
        temp.by=q.front().by+m[i].by;
        if(temp.by<1||temp.by>y)
            continue;
        if((map[temp.bx][temp.by]=='0'||map[temp.bx][temp.by]=='r')&&bfs(temp.rx,temp.ry,temp.bx-2*m[i].bx,temp.by-2*m[i].by)&&mrk[temp.bx][temp.by]<=2)
        {
            temp.rx=temp.bx-2*m[i].bx;
            temp.ry=temp.by-2*m[i].by;
            q.push(temp);
        }
    }
}
void move()//方便移动用的
{
    m[1].bx=-1;m[1].by=0;
    m[2].bx=1;m[2].by=0;
    m[3].bx=0;m[3].by=-1;
    m[4].bx=0;m[4].by=1;
}
int main()
{
    //freopen("input.txt","r",stdin);
    int n,i,j,endx,endy;
    node temp;
    bool flag;
    move();
    cin>>n;
    while(n--)
    {
        flag=false;
        memset(map,1,sizeof(map));
        scanf("%d %d",&x,&y);
        getchar();
        for(i=1;i<=x;i++)
        {
            for(j=1;j<=y;j++)
            {
                scanf("%c ",&map[i][j]);
                if(map[i][j]=='2')
                {
                    temp.bx=i;
                    temp.by=j;
                }
                else if(map[i][j]=='3')
                {
                    endx=i;
                    endy=j;
                    map[i][j]='0';
                }
                else if(map[i][j]=='4')
                {
                    temp.rx=i;
                    temp.ry=j;
                    map[i][j]='0';
                }
            }
        }
        map[temp.bx][temp.by]='0';//这个补丁直接搜人能不能走到箱子的终点,如果人都走不到,箱子也不可能到,算的搜的时候无视箱子
        if(!dfs(temp.rx,temp.ry,endx,endy))//一个补丁,用来处理奇怪的数据
        {
            cout<<"-1"<<endl;
            continue;
        }
        map[temp.bx][temp.by]='2';//补丁搜完了,箱子补上
        memset(mrk,0,sizeof(mrk));
        temp.num=0;
        q.push(temp);
        while(!q.empty())//广搜箱子路径
        {
            map[q.front().bx][q.front().by]='2';//每次要记录人的位置的改变
            mrk[q.front().bx][q.front().by]++;
            if(q.front().bx==endx&&q.front().by==endy)
            {
                cout<<q.front().num<<endl;
                flag=true;
                break;
            }
            next();
            map[q.front().bx][q.front().by]='0';
            q.pop();
        }
        if(!flag)
            cout<<"-1"<<endl;
        while(!q.empty())
            q.pop();
    }
    return 0;
}
bool bfs(int rx,int ry,int ex,int ey)//人的广搜函数,4个参数别是起始位置x,起始位置y,终点位置x,终点位置y
{
    node temp;
    memset(mark,true,sizeof(mark));
    temp.rx=rx;
    temp.ry=ry;
    rq.push(temp);
    while(!rq.empty())
    {
        if(rq.front().rx==ex&&rq.front().ry==ey)
        {
            while(!rq.empty())
        rq.pop();
            return true;
        }
        r_next();
        rq.pop();
    }
    while(!rq.empty())
        rq.pop();
    return false;
}
void r_next()//人的下一步计算函数
{
    node temp;
    int i;
    for(i=1;i<=4;i++)
    {
        temp.rx=rq.front().rx+m[i].bx;
        if(temp.rx<1||temp.rx>x)
            continue;
        temp.ry=rq.front().ry+m[i].by;
        if(temp.ry<1||temp.ry>y)
            continue;
        if(map[temp.rx][temp.ry]=='0'&&mark[temp.rx][temp.ry]!=false)
        {
            mark[temp.rx][temp.ry]=false;
            rq.push(temp);
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Y飞羽Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值