广搜习题

HDU1072 Nightmare

Nightmare

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 11091 Accepted Submission(s): 5401

Problem Description
Ignatius had a nightmare last night. He found himself in a labyrinth with a time bomb on him. The labyrinth has an exit, Ignatius should get out of the labyrinth before the bomb explodes. The initial exploding time of the bomb is set to 6 minutes. To prevent the bomb from exploding by shake, Ignatius had to move slowly, that is to move from one area to the nearest area(that is, if Ignatius stands on (x,y) now, he could only on (x+1,y), (x-1,y), (x,y+1), or (x,y-1) in the next minute) takes him 1 minute. Some area in the labyrinth contains a Bomb-Reset-Equipment. They could reset the exploding time to 6 minutes.

Given the layout of the labyrinth and Ignatius’ start position, please tell Ignatius whether he could get out of the labyrinth, if he could, output the minimum time that he has to use to find the exit of the labyrinth, else output -1.

Here are some rules:
1. We can assume the labyrinth is a 2 array.
2. Each minute, Ignatius could only get to one of the nearest area, and he should not walk out of the border, of course he could not walk on a wall, too.
3. If Ignatius get to the exit when the exploding time turns to 0, he can’t get out of the labyrinth.
4. If Ignatius get to the area which contains Bomb-Rest-Equipment when the exploding time turns to 0, he can’t use the equipment to reset the bomb.
5. A Bomb-Reset-Equipment can be used as many times as you wish, if it is needed, Ignatius can get to any areas in the labyrinth as many times as you wish.
6. The time to reset the exploding time can be ignore, in other words, if Ignatius get to an area which contain Bomb-Rest-Equipment, and the exploding time is larger than 0, the exploding time would be reset to 6.

Input
The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
Each test case starts with two integers N and M(1<=N,Mm=8) which indicate the size of the labyrinth. Then N lines follow, each line contains M integers. The array indicates the layout of the labyrinth.
There are five integers which indicate the different type of area in the labyrinth:
0: The area is a wall, Ignatius should not walk on it.
1: The area contains nothing, Ignatius can walk on it.
2: Ignatius’ start position, Ignatius starts his escape from this position.
3: The exit of the labyrinth, Ignatius’ target position.
4: The area contains a Bomb-Reset-Equipment, Ignatius can delay the exploding time by walking to these areas.

Output
For each test case, if Ignatius can get out of the labyrinth, you should output the minimum time he needs, else you should just output -1.

Sample Input
3
3 3
2 1 1
1 1 0
1 1 3
4 8
2 1 1 0 1 1 1 0
1 0 4 1 1 0 4 1
1 0 0 0 0 0 0 1
1 1 1 4 1 1 1 3
5 8
1 2 1 1 1 1 1 4
1 0 0 0 1 0 0 1
1 4 1 0 1 1 0 1
1 0 0 0 0 3 0 1
1 1 4 1 1 1 1 1

Sample Output
4
-1
13

Author
Ignatius.L

广搜,不过有一点值得注意的地方,这里不是走过就不能走了,而是只有当走过的点是重置炸弹的点时才标记不能再次走,这是因为有时为了能够多得一些时间,会绕道向炸弹重置区去走。

这里写代码片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<queue>
using namespace std;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int map[10][10];
int vis[10][10];
int m,n,sx,sy;
int i,j;
struct node
{
    int x,y;
    int time;
    int step;
};
void bfs()
{
    node p,r;
    queue<node>q;
    p.x=sx;
    p.y=sy;
    p.time=6;
    p.step=0;
    map[p.x][p.y]=0;
    q.push(p);
    while(!q.empty())
    {
        r=q.front();
        q.pop();
        if(map[r.x][r.y]==3)
        {
            cout<<r.step<<endl;
            return ;
        }
        if(r.time==1)
            continue;
        for(i=0;i<4;i++)
        {
            p.x=r.x+dir[i][0];
            p.y=r.y+dir[i][1];
            p.step=r.step+1;
            p.time=r.time-1;
            if(p.x<1||p.x>m||p.y<1||p.y>n||map[p.x][p.y]==0)
                continue;
            if(map[p.x][p.y]==4)
            {
                map[p.x][p.y]=0;//
                p.time=6;
            }
            q.push(p);
        }
    }
    cout<<"-1"<<endl;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(vis,0,sizeof(vis));
        cin>>m>>n;
        for(i=1;i<=m;i++)
            for(j=1;j<=n;j++)
        {
            cin>>map[i][j];
            if(map[i][j]==2)
            {
                sx=i;
                sy=j;
            }
        }
        bfs();
    }
    return 0;
}

A计划
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2102

思路:这道题以前写的时候觉得挺麻烦的,要判断的条件很多,不过练得多的话就会发现只要把所有要满足的条件判断一下就可以了。

代码:

#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
using namespace std;
int n,m,t;
char map[30][30];
int vis[30][30];
int to[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//四个方向
int ex,ey;
struct node
{
    int x,y,time;
};
int check(int i,int j,int i1,int j1)
{
    if(i>=0&&i<2*n&&j>=0&&j<m&&vis[i][j]==0&&map[i][j]!='*')
    {//保证不越界
        if((i1<n&&i<n)||(i1>=n&&i>=n))
            return 1;//保证向四个方向走后不越界
    }
    return 0;
}
int bfs()
{
    memset(vis,0,sizeof(vis));
    queue<node>Q;
    node p,next;
    int i;
    p.x=0;
    p.y=0;
    p.time=0;
    Q.push(p);
    vis[p.x][p.y]=1;
    while(!Q.empty())
    {
        p=Q.front();
        Q.pop();
        if(p.x==ex&&p.y==ey)
            return p.time;
        for(i=0;i<4;i++)
        {
           next.x=p.x+to[i][0];
           next.y=p.y+to[i][1];
           if(check(next.x,next.y,p.x,p.y)==1)
           {
                if(next.x<n)
                {//在第一层
                    if(map[next.x][next.y]=='#')
                    {//当前位置是时空传输机
                        if(map[next.x+n][next.y]=='#'||map[next.x+n][next.y]=='*')
                            continue;//如若传输后要去的地方是传输机或是墙
                        vis[next.x][next.y]=1;
                        next.x=next.x+n;
                    }
                }
                else
                {//在第二层
                    if(map[next.x][next.y]=='#')
                    {//当前位置是时空传输机
                        if(map[next.x-n][next.y]=='#'||map[next.x-n][next.y]=='*')
                            continue;//如若传输后要去的地方是传输机或是墙
                        vis[next.x][next.y]=1;
                        next.x=next.x-n;

                    }
                }
                vis[next.x][next.y]=1;
                next.time=p.time+1;
                Q.push(next);
           }
        }
    }
    return -1;
}
int main()
{
    int l;
    int i,j;
    scanf("%d",&l);
    while(l--)
    {
        scanf("%d%d%d",&n,&m,&t);
        for(i=0;i<n;i++)
        {//第一层
            for(j=0;j<m;j++)
            {
                cin>>map[i][j];
                if(map[i][j]=='P')
                {//记录公主的位置
                    ex=i;
                    ey=j;
                }
            }
        }
        for(i=n;i<2*n;i++)
        {//第二层
            for(j=0;j<m;j++)
            {//记录公主的位置
                cin>>map[i][j];
                if(map[i][j]=='P')
                {
                    ex=i;
                    ey=j;
                }
            }
        }
        int num=bfs();
        if(num<=t&&num!=-1)
        printf("YES\n");
        else
        printf("NO\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值