XTU热身赛出的题。本来这次比赛可以多些几道的,可惜脑袋浆糊掉了。。以后要更加努力,希望能超过师兄,师姐们啊。言归正传:
这道题首先一看,它就是一道搜索题。搜索题:一般无外乎两种方法 1、DFS。2、BFS。想了想DFS只要用一个标记pre[maxn][maxn]的数组记录前一个坐标的方向就行,如果和前面不同则step++。后来果断超时。于是想起了BFS,怎么去判断它是否转弯呢?一个方向搜到底,到底时换方向的时候拐弯数加一,那么出队再拓展路径的时候拐弯数肯定也要加一,因为与这个点在一条直线上的点已经全部入队了。于是就有了下面的代码:
#include <iostream>
#include <queue>
#include <cstdlib>
#include <cstring>
#include <cmath>
#define MAX_LEN 101
using namespace std;
struct node
{
int x,y;
int step ;
}in , out;
queue <node> Q;
const int move[4][2] = {-1,0, 0,1 , 1,0 , 0,-1};
int flag[MAX_LEN + 10][MAX_LEN + 10]; //标记
char map[MAX_LEN + 10][MAX_LEN + 10];
int n,m,bx,by,ex,ey,k; //入口坐标
void init()
{
memset(flag , false , sizeof(flag));
while(!Q.empty()) Q.pop();
memset(map , 0 , sizeof(map));
}
bool Check(int x, int y)
{
if(x >= 1 && x <= n && y >= 1 && y <= m && map[x][y] == '.') return true;
return false;
}
void BFS()
{
if(bx == ex && by == ey)
{
printf("yes\n");
return ;
}
flag[bx][by] = true;
in.x = bx; in.y = by ; in.step = -1;
Q.push(in);
while(!Q.empty())
{
out = Q.front();
Q.pop();
int x = out.x;
int y = out.y;
for(int i = 0; i < 4 ; i++)
{
int xx = x + move[i][0];
int yy = y + move[i][1];
while(Check(xx , yy))
{
if(flag[xx][yy] == false)
{
flag[xx][yy] = true;
in.x = xx;
in.y = yy;
in.step = out.step+1; //转弯的次数
Q.push(in);
if(in.x == ex && in.y == ey && in.step <= k)
{
printf("yes\n");
return ;
} //如果找到
}
xx += move[i][0];
yy += move[i][1];
}
}
}
printf("no\n");
return ;
}
int main()
{
int t;
while(~scanf("%d", &t))
{
while(t--)
{
init();
scanf("%d %d", &n , &m);
for(int i = 1;i <= n; i++)
{
for(int j = 1 ; j <= m ;j++)
scanf(" %c" , &map[i][j]);
}
scanf("%d%d%d%d%d", &k , &by , &bx , &ey , &ex);
BFS();
}
}
//system("pause");
return 0;
}
#include <queue>
#include <cstdlib>
#include <cstring>
#include <cmath>
#define MAX_LEN 101
using namespace std;
struct node
{
int x,y;
int step ;
}in , out;
queue <node> Q;
const int move[4][2] = {-1,0, 0,1 , 1,0 , 0,-1};
int flag[MAX_LEN + 10][MAX_LEN + 10]; //标记
char map[MAX_LEN + 10][MAX_LEN + 10];
int n,m,bx,by,ex,ey,k; //入口坐标
void init()
{
memset(flag , false , sizeof(flag));
while(!Q.empty()) Q.pop();
memset(map , 0 , sizeof(map));
}
bool Check(int x, int y)
{
if(x >= 1 && x <= n && y >= 1 && y <= m && map[x][y] == '.') return true;
return false;
}
void BFS()
{
if(bx == ex && by == ey)
{
printf("yes\n");
return ;
}
flag[bx][by] = true;
in.x = bx; in.y = by ; in.step = -1;
Q.push(in);
while(!Q.empty())
{
out = Q.front();
Q.pop();
int x = out.x;
int y = out.y;
for(int i = 0; i < 4 ; i++)
{
int xx = x + move[i][0];
int yy = y + move[i][1];
while(Check(xx , yy))
{
if(flag[xx][yy] == false)
{
flag[xx][yy] = true;
in.x = xx;
in.y = yy;
in.step = out.step+1; //转弯的次数
Q.push(in);
if(in.x == ex && in.y == ey && in.step <= k)
{
printf("yes\n");
return ;
} //如果找到
}
xx += move[i][0];
yy += move[i][1];
}
}
}
printf("no\n");
return ;
}
int main()
{
int t;
while(~scanf("%d", &t))
{
while(t--)
{
init();
scanf("%d %d", &n , &m);
for(int i = 1;i <= n; i++)
{
for(int j = 1 ; j <= m ;j++)
scanf(" %c" , &map[i][j]);
}
scanf("%d%d%d%d%d", &k , &by , &bx , &ey , &ex);
BFS();
}
}
//system("pause");
return 0;
}
这个题不一个方向搜到底肯定是错的,即使用优先队列把拐弯少的先出队来拓展路径也是不对的!
可以设想如果不把一个方向上的点先入队的话,那么有可能一个不需要拐弯的点在拓展时会被弄成要拐弯才能走到,这时候就不对了!
一个方向搜到底,搜到底时换方向的时候拐弯数加一,那么出队再拓展路径的时候拐弯数肯定也要加一,因为与这个点在一条直线上的点已经全部入队了。