NEUQ-ACM预备队训练-week4(搜索)

1.P1605 迷宫

戳这里跳到原题

题目描述

给定一个 N×M 方格的迷宫,迷宫里有 T 处障碍,障碍处不可通过。

在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。

输入格式

第一行为三个正整数 N,M,T 分别表示迷宫的长宽和障碍总数。

第二行为四个正整数 SX,SY,FX,FY,SX,SY 代表起点坐标,FX,FY 代表终点坐标。

接下来 T 行,每行两个正整数,表示障碍点的坐标。

输出格式

输出从起点坐标到终点坐标的方案总数。

输入输出样例

输入

2 2 1
1 1 2 2
1 2

输出

1

说明/提示

对于 100% 的数据,1≤N,M≤5,1≤T≤10,1≤SX,FX≤N,1≤SY,FY≤M。

从迷宫入口找到出口很明显是要用深搜来做,而且人家要求输出解的个数,所以就每次搜索以后就给他回溯一下,一直找直到碰到出口就结束,顺便把解的个数++,具体的做法我都在代码里面写成注释了,最后输出这个解的个数就AC了

#include <iostream>
using namespace std;
int sum = 0;
int x, y, mnt, sx, sy, fx, fy, arr[7][7] = {0};

void DFS(int x,int y) {
	arr[x][y] = 2;//标记这个点表示走过
	if(x == fx&&y == fy){//遇到出口就sum++并且return回去
		sum++;
		return;
	}
//  if(arr[x-1][y]==0){//如果没走过并且没有障碍
//      DFS(x-1,y);//继续深搜
//      arr[x-1][y] = 0;//回溯
//  }//下面都是一样的不过合成到一行了
	if(arr[x-1][y]==0){DFS(x-1,y);arr[x-1][y] = 0;}
	if(arr[x+1][y]==0){DFS(x+1,y);arr[x+1][y] = 0;}
	if(arr[x][y+1]==0){DFS(x,y+1);arr[x][y+1] = 0;}
	if(arr[x][y-1]==0){DFS(x,y-1);arr[x][y-1] = 0;}
}


int main() {
	//一堆输入
	cin >> x >> y >> mnt;
	cin >> sx >> sy >> fx >> fy;
	//地图的初始化
	for (int i = 0; i <= x + 1; i++) {
		for (int j = 0; j <= y + 1; j++) {
			if (i == 0 || i == x + 1  || j == 0 || j == y + 1 )
				arr[i][j] = 1;//墙都设成1
		}
	}
	int tempx, tempy;
	for (int i = 0; i < mnt; i++) {
		cin >> tempx >> tempy;
		arr[tempx][tempy] = 1;//障碍和墙一样看待,都不能走,设成1
	}

//	for (int i = 0; i <= x + 1; i++) {
//		for (int j = 0; j <= y + 1; j++) {
//			cout << arr[i][j] << ' ';
//		}
//		cout << endl;
//	}//输出地图检测输入是否正确
    //开搜
	DFS(sx,sy);
	cout << sum;
	return 0;
}

2.P1443 马的遍历

原题位置

题目描述

有一个 n×m 的棋盘,在某个点 (x, y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

输入格式

输入只有一行四个整数,分别为 n, m, x, y。

输出格式

一个 n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 −1)。

输入输出样例

输入

3 3 1 1

输出

0    3    2    
3    -1   1    
2    1    4    

说明/提示

数据规模与约定

对于全部的测试点,保证 1≤x≤n≤400,1≤y≤m≤400。

这个题一眼广搜,就是把遍历到的节点的下一步能走的节点给他放到队列里面,然后把这个节点赋值,再走到下一个节点,一层一层的搜索,直到队列里面没有新成员了,走不下去了,就可以退出了,直接把这个矩阵输出就OK,还是具体操作写在注释里,代码贴上

#include <iostream>
#include <cstring>
using namespace std;
#define MAXX 405
#define MAXY 405
#define DUILIE 164025

int main()
{
    //准备工作
	char arr[MAXX][MAXY];
	memset(arr,-1,MAXX*MAXY);//把这个矩阵初始化成-1表示没有走过
	int b[2][DUILIE];//用一个二维数组当队列了,第一行存x值,第二行存y值
	int dx[8]={-1,-2,-2,-1,1,2,2,1};
	int dy[8]={2,1,-1,-2,2,1,-1,-2};//把八个方向用数组存一下,后面直接遍历这个数组就OK
	int start = 0,end = 0;//用给队列的两个变量,存队列的头尾
	int n,m,x,y,step=0;//矩阵大小和初始位置都在这里,step是步数

    //开始输入
	cin >> n >> m >> x >> y ;
	arr[x][y] = 0;//起始位置设成0
	b[0][end] = x;
	b[1][end++] = y;//把起始位置压入队列
    
    //广搜开始
	while(start!=end){//只要队列里还有元素
		int temp = end;
		for(;start!=temp;start = (start+1)%DUILIE){
			//把相邻的位置压入队列
			for(int i=0;i<8;i++)
			{
				int nx=b[0][start]+dx[i],ny=b[1][start]+dy[i];
				if(nx>0&&nx<=n&&ny>0&&ny<=m&&arr[nx][ny]==-1){
					b[0][end] = nx;
					b[1][end] = ny;
					end = (end+1)%DUILIE;
					arr[nx][ny] = -2;//一定要设成跟-1不一样的区分一下,不然有可能多次压入
				}
			}
			arr[b[0][start]][b[1][start]] = step;//赋值
		}
		step++;//步数++
	}

    //简单输出
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= m;j++){
			printf("%-5d",arr[i][j]);
		}cout << endl;
	}

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值