蓝桥杯 学霸的迷宫(广搜,路径追踪)迷宫问题(vjudge,路径追踪)


学到的东西:

/*
记录路径的方法:
	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;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值