多校训练第四场
这是一个搜索的题目要用一次深搜找到初始位置,再用宽搜找到答案,首先分析一下题目发现,从起点来向周围的点搜索,如果发现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");
}
}
本文介绍了一种结合深度优先搜索与宽度优先搜索的算法,用于解决特定类型的搜索问题。该算法首先通过深度优先搜索找到初始位置,然后利用宽度优先搜索确定最优路径。文章详细解释了算法的工作原理,并提供了实现代码。

221

被折叠的 条评论
为什么被折叠?



