HDU 5335 Walk Out

本文介绍了一种结合深度优先搜索与宽度优先搜索的算法,用于解决特定类型的搜索问题。该算法首先通过深度优先搜索找到初始位置,然后利用宽度优先搜索确定最优路径。文章详细解释了算法的工作原理,并提供了实现代码。


多校训练第四场

这是一个搜索的题目要用一次深搜找到初始位置,再用宽搜找到答案,首先分析一下题目发现,从起点来向周围的点搜索,如果发现0则优先进入零,但是不进入1,如果没有0则都需要搜索一遍,不过我们再仔细分析题目就会发现,一旦第一个一进入则只可能向右或者下搜索,因为一旦有一出现那么向上或者向左搜索只会使数位更大,这是比踩1更可怕的事情,而对于一个点(x,y)来说最小的数位就是n- x + m - y如果比这个大的话就绝对不是最优解;由此我们发现我们首先要找到一个最佳的初始位位置,也就是数位最小而且可以通过一串0到达的位置,这个位置首先要用款搜找到,需要注意的是这个位置可能不止一个。好了找到最佳的初始位置之后我们需要做的就是搜索最佳路径,上面的分析告诉我们我们只可能向下和向右搜索,而且优先走0,遇到0绝对不走1,如果下一步全是1,那就都要搜索,于是这样就保证了搜索过的点走过的路径值是一样的而且是最优的,这样就不用一次一次的回去找路径再判断,因为搜索的每一个点都是最优的,再找到下一步中最优的存为要搜索的位置,当然如果那个位置在里面那就不用搜索了,这个栈是我用一个数组手写的,最后再用一个char 数组记录下路径,思路就是这样。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <functional>
#include <cstdio>
#include <queue>
#include <map>
#include <algorithm>
#include <stack>
#include <utility>
typedef long long ll;
using namespace std;
const int mx = 1009;
bool used[mx][mx];
int s[mx][mx],n,m,sum;
char str[mx << 1],cccc[mx];
int nod[mx << 1][2],num,cnt;
void bfs()
{
    int i,j,k,x,y,OK,a,b,all;
    while(sum < (m + n - 2))
    {
        OK = 1;
        for(i = 0; i < num && OK; i++)
        {
            k = nod[i][sum&1];
            x = k / m;
            y = k % m;
            if(y + 1 < m &&s[x][y + 1] == 0)
                OK = 0;
            if(x + 1 < n &&s[x + 1][y] == 0)
                OK = 0;
//                printf(" k = %d x = %d y = %d OK = %d\n",k,x,y,OK);
        }
        if(OK)
            str[cnt++] = '1';
        else
            str[cnt++] = '0';
        all = num;
        num = 0;
        a = sum & 1;
        b = (sum + 1) & 1;
        for(i = 0; i < all; i++)
        {
            k = nod[i][a];
            x = k / m;
            y = k % m;
            if(x + 1 < n && !used[x + 1][y] && s[x + 1][y] == OK)
                used[x + 1][y] = true,nod[num++][b] = k + m;
            if(y + 1 < m && !used[x][y + 1] && s[x][y + 1] == OK)
                used[x][y + 1] = true,nod[num++][b] = k + 1;
        }
        sum++;
    }
}
void dfs(int a,int b)
{
//    printf("a = %d b = %d\n",a,b);
    used[a][b] = true;
    if(s[a][b] == 1)
    {
        if(a + b == sum)
            nod[num++][sum&1] = a * m + b;
        if(a + b > sum)
        {
            sum = a + b;
            num = 0;
            nod[num++][sum&1] = a * m + b;
        }
        return;
    }
    if(a + b == n + m - 2)
    {
        sum = n + m - 2;
        return;
    }
    if(a + 1 < n &&!used[a + 1][b]) dfs(a + 1,b);
    if(b + 1 < m &&!used[a][b + 1]) dfs(a,b + 1);
    if(a > 0 && !used[a - 1][b]) dfs(a - 1,b);
    if(b > 0 && !used[a][b - 1]) dfs(a,b - 1);
}
int main ()
{
    int T,i,j,k;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(i = 0; i < n ; i++)
        {
            scanf("%s",cccc);
            for(j = 0; j < m; j++)
                s[i][j] = cccc[j] - '0';
        }
//        printf("awsdfasdf\n");
        memset(used,false,sizeof(used));
        sum = 0;
        dfs(0,0);
        if(sum == n + m - 2)
        {
            printf("%d\n",s[n - 1][m - 1]);
            continue;
        }
        memset(used,false,sizeof(used));
        cnt = 0;
        str[cnt++] = '1';
        bfs();
        for(i = 0; i < cnt; i++)
            printf("%c",str[i]);
        printf("\n");
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值