学到的东西:
/*
记录路径的方法:
1 string法。
2 记录方向法。
3 路径追踪法。
*/
分别对应以下三个代码:
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
int n,m;
char map[510][510];//存储地图;
int book[510][510];//标记是否搜索过;
int nextt[4][2]= {{1,0},{0,-1},{0,1},{-1,0}};//这个要注意,题目要求路径一样的按照字典序小的输出;
//按照字典序的顺序依次搜索 下,左,右,上;
char k[4]={'D','L','R','U'};
struct node
{
int x;
int y;
int step;
string s;//记录路径;
};
void bfs()
{
int i;
node a,b;
queue<node>Q;
memset(book,0,sizeof book);
book[0][0]=1;
a.x=0;
a.y=0;
a.step=0;
a.s="";//记得初始化;
Q.push(a);
while(!Q.empty())
{
a=Q.front();
Q.pop();
if(a.x==n-1&&a.y==m-1)//到了出口就结束,输出路径;
{
printf("%d\n",a.step);
cout<<a.s<<endl;
return ;
}
for(i=0; i<4; i++)//四个方向进行搜索;
{
b.x=a.x+nextt[i][0];
b.y=a.y+nextt[i][1];
b.step=a.step+1;
if(b.x<0||b.x>=n||b.y<0||b.y>=m)//判断边界;
continue;
if(book[b.x][b.y]==1||map[b.x][b.y]=='1')//判断是否搜索过,是否不能走;
continue;
b.s=a.s+k[i];//记录路径;
book[b.x][b.y]=1;//标记搜索过,忘记会超时;
Q.push(b);//进队列;
}
}
return ;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=0; i<n; i++)
{
scanf("%s",&map[i]);//字符串输人;
}
bfs();
}
return 0;
}
//80分
#include<iostream>
#include<cstring>
using namespace std;
int n,m;
int next[5][2]={0,0,1,0,0,-1,0,1,-1,0};
typedef struct node
{
int x;
int y;
int father;//记录队列里的父亲。
int sum;
int fx;//记录下一个的方向。
}Node;
char map[505][505];
int book[505][505];
int road[200000];
Node que[250003];
int main()
{
cin>>n>>m;
memset(map,0,sizeof(map));
memset(book,0,sizeof(book));
for (int i=0;i<n;i++)
cin>>map[i];
int head=0,tail=0,tx,ty;
book[0][0]=1;
que[tail].x=0;
que[tail].y=0;
que[tail].father=0;
que[tail].fx=0;
que[tail++].sum=0;//tail指向尾结点的下一个结点,head指向队头。
while (head<tail)//手工实现队列的队列不为空的方法。
{
if (que[head].x==m-1&&que[head].y==n-1)
break;
for (int k=1;k<=4;k++)
{
tx=que[head].x+next[k][0];
ty=que[head].y+next[k][1];
if (tx<0||tx>=n||ty<0||ty>=m)
continue;
if (book[tx][ty]==0&&map[tx][ty]=='0')
{
book[tx][ty]=1;
que[tail].x=tx;
que[tail].y=ty;
que[tail].father=head;//路径追踪。
que[tail].fx=k;
que[tail++].sum=que[head].sum+1;//路径长度始终等于父节点的路径长度+1.
}
}
head++;//出队操作。
}
cout<<que[head].sum<<endl;
int count=0;
while (head!=0)
{
road[count]=que[head].fx;
count++;
head=que[head].father;
}
for (int i=count-1;i>=0;i--)
{
if (road[i]==1)
cout<<"D";
else if (road[i]==2)
cout<<"L";
else if (road[i]==3)
cout<<"R";
else
cout<<"U";
}
return 0;
}
迷宫问题:
学到的东西:
路径追踪:记录前驱法(记录工作指针)。
由于我们记录前驱的目的是为了以后再访问该点,所以不能用stl里的队列(一pop就没了),只能用数组自己实现。
广搜要注意的问题是:
1 一定要将访问过的点标记好。
2 什么时候出队,什么时候入队。
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
char book[30][30];
int maze[26][26];
struct node{
int x,y;
string rt;
int pre;
};
node arr[50];
int dirx[]={0,0,-1,1};
int diry[]={1,-1,0,0};
int main()
{
/*
bfs记录路径。
两种方法:
1 用队列记录工作指针(记录前驱)。
2 用string类型存储。
*/
for(int i=0;i<5;i++){
for(int j=0;j<5;j++) cin>>maze[i][j];
}
int head=0,tail=0;
node nd1;
nd1.x=0;
nd1.y=0;
book[nd1.x][nd1.y]=1;
nd1.pre=-1;
arr[head]=nd1;
tail++;
bool flag=false;
while(head<tail){
nd1=arr[head];
for(int i=0;i<4;i++){
int x=nd1.x+dirx[i];
int y=nd1.y+diry[i];
if(x>=0&&x<=4&&y>=0&&y<=4&&maze[x][y]==0&&!book[x][y]){
arr[tail].x=x;
arr[tail].y=y;
arr[tail].pre=head;
book[x][y]=1;
if(x==4&&y==4){
flag=true;
break;
}
tail++;
}
}
if(flag) break;
head++;
}
node root[20];
head=0;
int t=arr[tail].pre;
root[head].x=arr[tail].x;
root[head].y=arr[tail].y;
head++;
while(t!=-1){
root[head++]=arr[t];
t=arr[t].pre;
}
head--;
for(int i=head;i>=0;i--){
cout<<"("<<root[i].x<<", "<<root[i].y<<")\n";
}
return 0;
}