day_12-acm 第二周bfs+dfs大总结

3 篇文章 0 订阅
1 篇文章 0 订阅

bfs+dfs

不罗嗦解释什么了,对广搜和深搜有疑问(戳这里)。忙活了一个礼拜了,直接上这一周的题目吧

A:Catch That Cow

hdu 2717

Problem Description

Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.

  • Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
  • Teleporting: FJ can move from any point X to the point 2 × X in a single minute.

If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

Input

Line 1: Two space-separated integers: N and K

Output

Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.

Sample Input

5 17

Sample Output

4

Hint

The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.

分析:

两种行走路径,左右移动1步或者穿越到当前位置的两倍上,最朴素的广度搜索了。

代码

#include <iostream>
#include <stack>
#include <cstring>
#include <queue>
#include <vector>
#include <cstdio>
#include <cmath>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define M 100001
#define INF 10000000

int n,k;
struct POINT
{
    int pos,step;
}now,next;

bool visited[M];

int bfs()
{
    queue<POINT>Q;
    while (!Q.empty())
        Q.pop();
    now.pos=n;
    now.step=0;
    visited[now.pos]=true;
    Q.push(now);
    while (!Q.empty())
    {
        now=Q.front();
        Q.pop();
        next=now;
        for (int i=0;i<3;i++)
        {
            if(i==0)
                next.pos=now.pos+1;
            if(i==1)
                next.pos=now.pos-1;
            if(i==2)
                next.pos=now.pos*2;
            next.step=now.step+1;
            if(next.pos==k)
                return next.step;
            if(next.pos<0||next.pos>M)
                continue;

            if(!visited[next.pos])
            {
                visited[next.pos]=true;
                Q.push(next);
            }
        }
    }
    return INF;
}

int main()
{

   cin>>n>>k;

        memset(visited,false,sizeof(visited));
        if(n<k)
            cout<<bfs()<<endl;
        if(n>k)
            cout<<n-k<<endl;
        if(n==k)
            cout<<0<<endl;

    return 0;
}

B: 迷宫问题

poj 3984

Description

定义一个二维数组:

int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

Input

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

Output

左上角到右下角的最短路径,格式如样例所示。

Sample Input

0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

Sample Output

(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

分析

这道题目若是简单的找寻路径就可以了,那么也算了简单的广搜了,但是他还要求输出经过的路径,讲真的刚开始几天只在网上找寻资源学习bfs,自己怎么也没法用bfs解决掉问题,然后看了题解,才知道这道题需要使用栈来存储他经过的路径,需要dfs。然后自己也修改了一下题解的代码。

代码

#include <iostream>
#include <stack>
#include <cstring>
#include <queue>
#include <vector>
#include <cstdio>
#include <cmath>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;

struct  node
{
   int a,b;
};

int maze[5][5];
bool vis[5][5];

stack <node>  passby;

int n;
void dfs(int x,int y)
{
    if(!vis[x][y])     // 如果没有访问过
    {
        node cur;
        cur.a=x;
        cur.b=y;
        vis[x][y]=1;    //已访问
        passby.push(cur);   //进栈
    }
    if(x==4&&y==4)
        return ;
    if(!vis[x+1][y]&&!maze[x+1][y]) //没有经过且可以经过
        dfs(x+1,y);
    else if(!vis[x][y+1]&&!maze[x][y+1])
        dfs(x,y+1);
    else
    {
        passby.pop();
        node cur=passby.top();
        dfs(cur.a,cur.b);
    }
}

int main()
{
   for(int i=0;i<5;i++)
     for(int j=0;j<5;j++)
        scanf("%d",&maze[i][j]);
   dfs(0,0);
   vector<node>v;
   while(!passby.empty())
   {
       v.push_back(passby.top());
       passby.pop();
   }
   for(int i=v.size()-1;i>=0;i--)
   {
       printf("(%d, %d)\n",v[i].a,v[i].b);
   }
   return 0;
}

C: 胜利大逃亡(续)

hdu 1429
这一题还没有做出来,至今还没有想到什么好的思路,今天一天都在纠结这个题目,然后看题解需要用到状态压缩,楞逼我一脸,渣渣表示学个bfs就花了整整一周时间。留到周末来解决状态压缩吧。

D: Knight Moves

poj 1915

Description

Background
Mr Somurolov, fabulous chess-gamer indeed, asserts that no one else but him can move knights from one position to another so fast. Can you beat him?
The Problem
Your task is to write a program to calculate the minimum number of moves needed for a knight to reach one point from another, so that you have the chance to be faster than Somurolov.
For people not familiar with chess, the possible knight moves are shown in Figure 1.

Input

The input begins with the number n of scenarios on a single line by itself.
Next follow n scenarios. Each scenario consists of three lines containing integer numbers. The first line specifies the length l of a side of the chess board (4 <= l <= 300). The entire board has size l * l. The second and third line contain pair of integers {0, …, l-1}*{0, …, l-1} specifying the starting and ending position of the knight on the board. The integers are separated by a single blank. You can assume that the positions are valid positions on the chess board of that scenario.

Output

For each scenario of the input you have to calculate the minimal amount of knight moves which are necessary to move from the starting point to the ending point. If starting point and ending point are equal,distance is zero. The distance must be written on a single line.

Sample Input

3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1

Sample Output

5
28
0

分析

这道题是bfs+模拟的典型模板了,用dir数组存储可能经过的路径。就可以来广搜了。

代码

#include <iostream>
#include <stack>
#include <cstring>
#include <queue>
#include <vector>
#include <cstdio>
#include <cmath>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define Max 310
int map[Max][Max];
int dir[8][2]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,-2},{2,-1},{2,1},{1,2}};
int flag[Max][Max];

int l;
int x2;
int y2;

struct point
{
    int x,y;
    int step;
};

int bfs(int a,int b)
{
    queue<point>Q;
    while (!Q.empty())
            Q.pop();
    point p;
    p.x=a;
    p.y=b;
    p.step=0;
    Q.push(p);
    flag[a][b]=1;
    while (!Q.empty())
    {
        point now=Q.front();
        Q.pop();
        if(now.x==x2&&now.y==y2)
            return now.step;
        for (int i=0;i<8;i++)
        {
            int nx=now.x+dir[i][0];
            int ny=now.y+dir[i][1];
            if(nx==x2&&ny==y2)
                return now.step+1;
            if(nx>=0&&nx<l&&ny>=0&&ny<l&&!flag[nx][ny])
            {
                int step=now.step+1;
                point next;
                next.x=nx;
                next.y=ny;
                next.step=step;
                Q.push(next);
                flag[nx][ny]=1;
            }
        }
    }
return 0;
}

int main ()
{

    int n;
    scanf("%d",&n);
    while (n--)
    {
        int x1,y1;
        memset(flag,0,sizeof(flag));
        scanf ("%d",&l);
        scanf ("%d%d%d%d",&x1,&y1,&x2,&y2);
        flag[x1][y1]=1;
        if(x1==x2&&y1==y2)
            printf ("0\n");
        else
        {
            int ans=bfs(x1,y1);
            printf ("%d\n",ans);
        }

    }
    return 0;
}

总结

这道题wa了三次,因为搜索越界了,if(nx>=0&&nx<l&&ny>=0&&ny<l&&!flag[nx][ny])这里一直判断小于等于 l 。

E:Dating with girls(2)

hdu 2579

Problem Description

If you have solved the problem Dating with girls(1).I think you can solve this problem too.This problem is also about dating with girls. Now you are in a maze and the girl you want to date with is also in the maze.If you can find the girl, then you can date with the girl.Else the girl will date with other boys. What a pity!
The Maze is very strange. There are many stones in the maze. The stone will disappear at time t if t is a multiple of k(2<= k <= 10), on the other time , stones will be still there.
There are only ‘.’ or ‘#’, ’Y’, ’G’ on the map of the maze. ’.’ indicates the blank which you can move on, ‘#’ indicates stones. ’Y’ indicates the your location. ‘G’ indicates the girl’s location . There is only one ‘Y’ and one ‘G’. Every seconds you can move left, right, up or down.

Input

The first line contain an integer T. Then T cases followed. Each case begins with three integers r and c (1 <= r , c <= 100), and k(2 <=k <= 10).
The next r line is the map’s description.

Output

For each cases, if you can find the girl, output the least time in seconds, else output “Please give me another chance!”.

Sample Input

1
6 6 2
…Y..
…#..
.#….
…#..
…#..
..#G#.

Sample Output

7

分析

这道题挺有意思的,带’#’的石块还会定时消失,所以说vis数组来个三维的,第三维用来判断石头是不是消失的,也就是能不能经过石头。

代码

#include <iostream>
#include <stack>
#include <cstring>
#include <queue>
#include <vector>
#include <cstdio>
#include <cmath>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
char map[110][110];
int vis [110][110][10];
int dir[4][2]={-1,0,1,0,0,1,0,-1};

struct point
{
    int x,y,t;
}start,last;
int r,c,k;

void bfs()
{
    queue <point>Q;
    while (!Q.empty())
        Q.pop();
    start.t=0;
    Q.push(start);
    while (!Q.empty())
    {
        point now,next;
        now=Q.front();
        Q.pop();
        if(map[now.x][now.y]=='G')
        {
            printf ("%d\n",now.t);
            return ;
        }
        for (int i=0;i<4;i++)
        {
            int nx=now.x+dir[i][0];
            int ny=now.y+dir[i][1];
            if(nx>=0&&nx<r&&ny>=0&&ny<c&&(map[nx][ny]!='#'||(now.t+1)%k==0)&&!vis[nx][ny][(now.t+1)%k])
            {
                next.t=now.t+1;
                next.x=nx;
                next.y=ny;
                vis[nx][ny][(now.t+1)%k]=1;
                Q.push(next);
            }
        }
    }
}

int main ()
{
    int T;
    scanf ("%d",&T);
    while (T--)
    {
        memset(vis,0,sizeof(vis));
        scanf ("%d%d%d",&r,&c,&k);
        for (int i=0;i<r;i++)
        {
            scanf ("%s",map[i]);
            for (int j=0;j<c;j++)
            {
                if(map[i][j]=='Y')
                {
                    start.x=i;
                    start.y=j;
                }
                if(map[i][j]=='G')
                {
                    last.x=i;
                    last.y=j;
                }
            }
        }
        bfs();
    }
    return 0;
}

总结

这题其实是有个坑点的,就是你这一次碰到的是石头,但是你装一圈回来石头可能就是消失状态的。

F:Open the Lock

hdu 1195

Problem Description

Now an emergent task for you is to open a password lock. The password is consisted of four digits. Each digit is numbered from 1 to 9.
Each time, you can add or minus 1 to any digit. When add 1 to ‘9’, the digit will change to be ‘1’ and when minus 1 to ‘1’, the digit will change to be ‘9’. You can also exchange the digit with its neighbor. Each action will take one step.

Now your task is to use minimal steps to open the lock.

Note: The leftmost digit is not the neighbor of the rightmost digit.

Input

The input file begins with an integer T, indicating the number of test cases.

Each test case begins with a four digit N, indicating the initial state of the password lock. Then followed a line with anotther four dight M, indicating the password which can open the lock. There is one blank line after each test case.

Output

For each test case, print the minimal steps in one line.

Sample Input

2
1234
2144

1111
9999

Sample Output

2
4

分析

开始看这个题目的时候,一看就知道bfs了,就匆匆忙忙的做了,样例都不瞄一眼,我也不知道我是哪来的信心,是做bfs做的顺手了嘛。。。。。。然后当然就是样例都没有过,再看题目发现可以交换的那个条件都没有注意到,以为就是跟自己的行李箱一样,就是没有0而已。。。而且开始还打算将数据%9,结果又发现虽然能够解决9到1,但是9本身就。。。然后还是老老实实的特判一下了。

代码

#include <iostream>
#include <stack>
#include <cstring>
#include <queue>
#include <vector>
#include <cstdio>
#include <cmath>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;

struct node
{
    int num[4],step;
} first,last;

int vis[11][11][11][11];

void bfs()
{
    int i;
    node p,now,next;
    queue<node> Q;
    p = first;
    p.step = 0;
    Q.push(p);
    vis[p.num[0]][p.num[1]][p.num[2]][p.num[3]] = 1;
    while(!Q.empty())
    {
        now = Q.front();
        Q.pop();
        if(now.num[0] == last.num[0] && now.num[1] == last.num[1] && now.num[2] == last.num[2] && now.num[3] == last.num[3])
        {
            printf("%d\n",now.step);
            return ;
        }
        for(i = 0; i<4; i++) //+1
        {
            next = now;
            next.num[i]++;
            if(next.num[i]==10)
                next.num[i] = 1;
            if(!vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]])
            {
                vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]] = 1;
                next.step++;
                Q.push(next);
            }
        }
        for(i = 0; i<4; i++) //-1
        {
            next = now;
            next.num[i]--;
            if(next.num[i]==0)
                next.num[i] = 9;
            if(!vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]])
            {
                vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]] = 1;
                next.step++;
                Q.push(next);
            }
        }
        for(i = 0; i<3; i++) //jiaohuan
        {
            next = now;
            next.num[i] = now.num[i+1];
            next.num[i+1] = now.num[i];
            if(!vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]])
            {
                vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]] = 1;
                next.step++;
                Q.push(next);
            }
        }
    }
}

int main ()
{
    int T;
    scanf ("%d",&T);
    while (T--)
    {
        char s1[10],s2[10];
        scanf ("%s%s",s1,s2);
        for (int i=0;i<4;i++)
        {
            first.num[i]=s1[i]-'0';
            last.num[i]=s2[i]-'0';
        }
        memset (vis,0,sizeof (vis));
        bfs();
    }
    return 0;
}


大总结

算法之巧妙、美妙、奇妙、好妙。。。。等等,容我脑子好好缓存缓存。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值