C
输入
1 3 5 s...x x...x ...tx
输出
YES
额外测试样例1:
2
5 5
.s..x
.xxx.
.xt..
.xxx.
.....
5 5
.s..x
.xxx.
.xt..
.xxx.
.....
额外测试样例2:
2
5 5
.s..x
.xxx.
.xt..
.xxx.
.....
5 5
.s.x.
..x.t
.x...
x....
.....
发现一些细节
1.牛客网是linux系统的编译器
2.这样子清空queue居然会报错
换成一个标记就对了
3.位置坐标一般表示所处行列 与在平面直角坐标系里的常规(x,y)有区别
容易弄混
AC代码
#include<iostream>
#include<algorithm>
#include<functional>
#include<queue>
#include<stack>'
#include<cstdlib>
#include<cstdio>
//#include<windows.h>
#include<unistd.h>
#include<string.h>
using namespace std;
char a[1000][1000];
int v[1000][1000] = { 0 };
string path;
int dx[4] = { 0, 1, 0, -1 };
int dy[4] = { 1, 0, -1, 0 };
//拓展点坐标
// int tx,ty;
// tx=x+dx[k];
// ty=y+dy[k];
struct point
{
int x;
int y;
// int step;
};
int main()
{
int n, m;//数组长宽
int startx, starty;//起点
int endx, endy;//终点 p q
int T;
//cout << "请输入测试组数" << endl;
cin >> T;
int i, j, k;
//cout<<"请输入"<<endl;
while (T--)
{
//cout << "请输入数组规模 行 / 列" << endl;
cin >> n >> m;
queue<point> myqueue;
memset(v,0,sizeof(v));
int f = 0;//方案有无 标记
//录入数据
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
{
cin >> a[i][j];
if (a[i][j] == 's')
{
startx = i;
starty = j;//注意配对
}
else if (a[i][j] == 't')
{
endx = i;
endy = j;
}
//原先是 1障碍物 0可行
else if (a[i][j] == 'x')
{
v[i][j] = 1;//表示不可走
}
}
//广搜
point start;
start.x = startx;
start.y = starty;
myqueue.push(start);
v[startx][starty] = 1;//标记起点
int index=0;
while (!myqueue.empty())//为空队判断
{
//取队首的x , y
if(index==1)
break;
int x = myqueue.front().x;
int y = myqueue.front().y;
//cout << "比较" << x << " " << endx << " " << y << " " << endy << endl;
//cout << "当前点 坐标" << x << " " << y << endl;
for (k = 0; k < 4; k++)
{
//拓展点坐标
int tx, ty;
tx = x + dx[k];
ty = y + dy[k];
//cout << "拓展点坐标" << tx << " " << ty << " " << endl;
if (tx == endx && ty == endy)
{
f = 1;
//cout<<r.front().step<<endl;
cout << "YES" <<endl;
//while(!myqueue.empty())
// myqueue.pop(); // 居然会爆段错误!!
index=1;
break ;//要多次 不能直接return0
}
//if(a[tx][ty]=='.' && v[tx][ty]==0 &&tx>=1&&tx<=n&&ty>=0&&ty<=m)
if (a[tx][ty] == '.' && v[tx][ty] == 0 && tx >= 1 && tx <= n && ty >= 1 && ty <= m)
//a 迷宫中能走 标记数组表示未访问
{
point temp;
temp.x = tx;
temp.y = ty;
myqueue.push(temp);
//标记访问信息
v[tx][ty] = 1;
}
}
myqueue.pop();
}
if (!f)
cout << "NO" << endl;
}
/*
* 2
5 5
.s..x
.xxx.
.xt..
.xxx.
.....
*/
return 0;
}
*调试代码(需要调试看着这里)
有部分问题,请参照上文
#include<iostream>
#include<algorithm>
#include<functional>
#include<queue>
#include<stack>'
#include<cstdlib>
#include<cstdio>
#include<windows.h>
using namespace std;
char a[100][100];
int v[100][100] = { 0 };
string path;
int dx[4] = { 0, 1, 0, -1 };
int dy[4] = { 1, 0, -1, 0 };
//拓展点坐标
// int tx,ty;
// tx=x+dx[k];
// ty=y+dy[k];
struct point
{
int x;
int y;
// int step;
};
int main()
{
int n, m;//数组长宽
int startx, starty;//起点
int endx, endy;//终点 p q
int T;
//cout << "请输入测试组数" << endl;
cin >> T;
int i, j, k;
//cout<<"请输入"<<endl;
while (T--)
{
//cout << "请输入数组规模 行 / 列" << endl;
cin >> n >> m;
queue<point> myqueue;
memset(v,0,sizeof(v));
int f = 0;//方案有无 标记
//录入数据
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
{
cin >> a[i][j];
if (a[i][j] == 's')
{
startx = i;
starty = j;//注意配对
}
else if (a[i][j] == 't')
{
endx = i;
endy = j;
}
//原先是 1障碍物 0可行
else if (a[i][j] == 'x')
{
v[i][j] = 1;//表示不可走
}
}
/*
for(i=1; i<=n; i++)
{
for(j=1; j<=m; j++)
{
cout<<a[i][j];
}
cout<<endl;
}
*/
//cout << "起点" << " " << startx << " " << starty << endl;
//cout << "终点" << " " << endx << " " << endy << endl;
/*
for (i = 1; i <= n; i++)
{
for (j = 1; j <= m; j++)
{
cout << v[i][j] << " ";
}
cout << endl;
}
cout << "最初道路状况" << endl;
*/
//广搜
point start;
start.x = startx;
start.y = starty;
//start.step=0;
//起点入队
myqueue.push(start);
v[startx][starty] = 1;//标记起点
while (!myqueue.empty())//为空队判断
{
//取队首的x , y
int x = myqueue.front().x;
int y = myqueue.front().y;
//cout << "比较" << x << " " << endx << " " << y << " " << endy << endl;
/*
if (x == endx && y == endy)
{
f = 1;
//cout<<r.front().step<<endl;
cout << "YES" << endl;
break;
}
*/
//cout << "当前点 坐标" << x << " " << y << endl;
for (k = 0; k < 4; k++)
{
//拓展点坐标
int tx, ty;
tx = x + dx[k];
ty = y + dy[k];
//cout << "拓展点坐标" << tx << " " << ty << " " << endl;
if (tx == endx && ty == endy)
{
f = 1;
//cout<<r.front().step<<endl;
cout << "YES" <<endl;
while(!myqueue.empty())
myqueue.pop();
break ;//要多次 不能直接return0
}
//if(a[tx][ty]=='.' && v[tx][ty]==0 &&tx>=1&&tx<=n&&ty>=0&&ty<=m)
if (a[tx][ty] == '.' && v[tx][ty] == 0 && tx >= 1 && tx <= n && ty >= 1 && ty <= m)
//a 迷宫中能走 标记数组表示未访问
{
//入队
//队列是结构体类型
//要存起来
point temp;
temp.x = tx;
temp.y = ty;
//temp.step=r.front().step+1;
//将数据入队
//cout << "入队一个" << endl;
myqueue.push(temp);
//标记访问信息
v[tx][ty] = 1;
}
/*
cout << "道路状况" << endl;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= m; j++)
{
cout << v[i][j] << " ";
}
cout << endl;
}*/
//Sleep(1000);
//出队出早了
}
//将队首出队
myqueue.pop();
}
if (!f)
cout << "NO" << endl;
/*
* cout << "道路状况" << endl;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= m; j++)
{
cout << v[i][j] << " ";
}
cout << endl;
}
*/
}
/*
* 2
5 5
.s..x
.xxx.
.xt..
.xxx.
.....
*/
return 0;
}
下面的话,暂时可以不用看下下去了,调试了三个多小时还是有问题……
主要是吧记录路径的算法改了一下
用一个二维结构体数组保存该点的上一步坐标,和移动方向
但是还是会超时
struct father
{
int fx,fy; //上一步坐标
char op; //上一步操作
};
调试代码
#include<iostream>
#include<algorithm>
#include<functional>
#include<queue>
#include<stack>'
#include<cstdlib>
#include<cstdio>
using namespace std;
char a[100][100];
int v[100][100]= {0};
string path;
//a 迷宫数组
//v 访问数组
//右 下 左 上 x ,y对应的偏移量
//int dx[4]= {0, 1, 0,-1};
//int dy[4]= {1, 0, -1, 0};
//下 左 右 上 就是字典序 DLRU
int dx[4]= {1, 0, 0, -1};
int dy[4]= {0, -1, 1, 0};
struct point
{
int x;
int y;
int step;
};
struct father
{
int fx,fy; //上一步坐标
char op; //上一步操作
};
father newmap[100][100];
queue<point> r;
int main()
{
// debug logs:
// * 1.方向数组由 从右开始顺时针 改为字典序搜索 DLRU
// * 2. 79行忘记了 越界判断 造成了输出路径错误
int n,m;//数组长宽
int startx,starty;//起点
int endx,endy;//终点
int f=0;//方案有无 标记
//cout<<"请输入数组规模 行 / 列"<<endl;
cin>>n>>m;
int i,j,k;
//cout<<"请输入"<<endl;
for(i=1; i<=n; i++)
for(j=1; j<=m; j++)
cin>>a[i][j];
startx=1;
starty=1;
endx=n;
endy=m;
//广搜
point start;
start.x=startx;
start.y=starty;
start.step=0;
newmap[start.x][start.y].fx=-1;
newmap[start.x][start.y].fy=-1;
newmap[start.x][start.y].op='X';
//初始化
//起点入队
r.push(start);
v[startx][starty]=1;//标记起点
while(!r.empty())//为空队判断
{
//取队首的x , y
int x =r.front().x;
int y =r.front().y;
if(x==endx &&y==endy)
{
f=1;
cout<<r.front().step<<endl;
break;
}
for( k=0; k<4; k++)
{
//拓展点坐标
int tx,ty;
tx=x+dx[k];
ty=y+dy[k];
if(a[tx][ty]=='0' && v[tx][ty]==0 &&tx>=1&&tx<=n&&ty>=0&&ty<=m)
//a 迷宫中能走 标记数组表示未访问
{
//入队
//队列是结构体类型
//要存起来
point temp;
temp.x=tx;
temp.y=ty;
temp.step=r.front().step+1;
//将数据入队
r.push(temp);
//标记访问信息
v[tx][ty]=1;
newmap[tx][ty].fx=x;
newmap[tx][ty].fy=y;
if(k==0)
newmap[tx][ty].op='D';
else if(k==1)
newmap[tx][ty].op='L';
else if(k==2)
newmap[tx][ty].op='R';
else if(k==3)
newmap[tx][ty].op='U';
//记录路径信息
}
//出队出早了
}
//将队首出队
r.pop();
}
if(!f)
cout<<"no answer!"<<endl;
//cout<<"道路状况"<<endl;
else
{
//回溯
for(i=1; i<=5; i++)
{
for(j=1; j<=5; j++)
{
//cout<< newmap[i][j].fx <<" "<<newmap[i][j].fy<<"*";
cout<<newmap[i][j].op<<"*";
}
cout<<endl;
}
int x=endx;
int y=endy;
string newst;
//忘记吧终点入栈了
//cout<<newmap[x][y].op<<endl;
newst=newst+newmap[x][y].op;
cout<<newst<<endl;
/*
5 5
00000
11110
00000
01111
00000
*/
while(1)
{
cout<<"当前"<<x<<" "<<y<<" ";
x=newmap[x][y].fx;
y=newmap[x][y].fy;
cout<<"下一步"<<newmap[x][y].op<<endl;
newst=newst+newmap[x][y].op;
if(newmap[x][y].op=='X')
break;
}
for(i=newst.length()-2; i>=0; i--)
{
cout<<newst[i];
}
}
cout<<endl;
for(i=1; i<=n; i++)
{
for(j=1; j<=m; j++)
{
cout<<v[i][j]<< " ";
}
cout<<endl;
}
//system("pause");
cout<<"起始位置"<<startx<<starty<<endl;
cout<<"终点位置"<<endx<<endy<<endl;
// cout<<"开始溯源"<<endl;//p,q;
//这个回溯算法不行
//p 行 搞错了 淦
/*
cout<<"道路状况"<<endl;
for(i=1; i<=n; i++)
{
for(j=1; j<=m; j++)
{
cout<<v[i][j]<< " ";
}
cout<<endl;
}
//DLRU
测试数据:
8 8
00000101
01010011
10101001
11110000
01101001
00011000
00101000
01111100
*/
return 0;
}