pku 3009 Curling 2.0

非常好的一道搜索题,花了一个下午和一个晚上去做去理解

题意:虽然英语很长,不过不是太难懂,就是可以向四个方向扔小球,每次扔出去,会一直走,直到遇到墙时停止,或出界失败,而遇到墙后,球会停止,然后所撞到的墙消失,给一个起点和一个终点,能在10步之内到达的则输出其最少步数

思路:虽然是搜dfs题目搜到的这道题,但是开始看题意是说要求最少的步数,第一个想到的自然是BFS,感觉稍微变形下,类似回溯,只是每次都是四个方向同时判断,然后入队,再继续广搜。然而,花了整整2个多小时,依然调不好,思路也越来越乱了,上百度搜了下,全是dfs的解法。仔细看了下,发现和自己写的bfs几乎一致,于是,决定从新再写一遍,改一改回溯,希望能更短时间内完成,而且图不大,空间换时间还是值得的。当然,更主要的原因是,不知道没理解为什么最少步数却没人用bfs呢……

但当我正真再次改的时候,突然发现了问题所在,因为bfs是同时想各个方向的,而每次如果撞到一面墙A,而另一方向搜的时候,这个被撞的墙A还是存在的,所以要做bfs理论上也是可以的,只是每次向外搜索一次,每个方向都应该增加一个20*20的数组,这个空间是否开的起真是一个问题……而且即使开的起,也是极不划算的,因为题目只要在10次之内,所以dfs也不会浪费太多时间

以下是代码,改自网上一个代码(ps:他的代码当时还开了一个宽搜用的结构体数组,没有删掉,呵呵,看来不止我一个人遇到这个问题)

code:

#include <iostream>
#include <cstdio>
using namespace std;
const int N = 25;
int sqr[N][N], w , h;
int dir[4][2] = {{1 , 0} , {-1 , 0} , {0 , -1} , {0 , 1}};
int ret ;

void DFS(int a , int b , int step)
{
    if(step > 10 || step > ret) return;
    for(int i=0; i < 4; i++)
    {
        int at = a + dir[i][0];
        int bt = b + dir[i][1];
        if(at <= 0 || bt <= 0 || at > h || bt > w)
            continue;
        if(sqr[at][bt] == 1) continue;
        int flag = 0;
        int tx = a , ty = b;
        while(sqr[at][bt] != 1)
        {
            tx = at, ty = bt;
            if(sqr[at][bt] == 3 && step + 1 <= 10)
            {
                ret = min(ret , step + 1);
            }
            at += dir[i][0];
            bt += + dir[i][1];
            if(at <= 0 || bt <= 0 || at > h || bt > w)
            {
                flag = 1;
                break;
            }
        }
        if(flag) continue;
        sqr[at][bt] = 0;
        DFS(tx , ty , step + 1);
        sqr[at][bt] = 1;
    }
}

int main()
{
    //freopen("in.txt" , "r" , stdin);
    while(scanf("%d %d" , &w , &h), w && h)
    {
        int sx ,sy;
        ret = 20;
        for(int i=1; i <= h; i++)
            for(int j=1; j <= w; j++)
            {
                scanf("%d" , &sqr[i][j]);
                if(sqr[i][j] == 2)
                {
                    sx = i;
                    sy = j;
                }
            }
        DFS(sx , sy , 0);
        printf("%d\n" , ret == 20 ? -1 : ret);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/FreeAquar/p/2029897.html