对称迷宫

描述

wlxsq有一个N*NN∗N的网格迷宫,每一个网格都有一个字母编号。

他要从左上角(1,1)(1,1)出发,走到右下角(n,n)(n,n),由于wlxsq很懒,所以他每次只会往右或者往下走一格。
由于最后到终点的路径方案太多太多了,所以wlxsq想让你计算出所有不同的对称的路径个数。
例如:N = 3N=3
ABA
BBB
ABA
对称路径6条:有ABABA(2条)、ABBBA(4条)
不同的对称路径有: 有ABABA、ABBBA

输入
第一行输入一个数NN,表示迷宫的大小。
接下来输入N*NN∗N的字母迷宫

输出
输出对称路径的数量

样例
3
ABA
BBB
ABA

输出
2

提示
【评测用例规模与约定】
对于40%40%的数据,2<=N<=112<=N<=11

对于100%100%的数据,2<=N<=182<=N<=18



在这一题种我们一般会想到先整体深搜一便保存所有路径,然后再判断是不是对称路径,然后再进行判重,但是这是一种完全暴力的方法,虽然一开始我也是这样做的O(∩_∩)O,这样不仅会超时,还会爆内存,逼近最大的图是18路劲大概有2^18次方条。
我们搞算法的就要尽可能的优化它,于是有了第二种思路
搜索两遍,第一遍从1,1位置搜索,第二遍从n,n位置搜索,分别保存路径和末尾点,然后再比对末尾点是否相同,路径是否相同,这里的路劲也是一个非常庞大的数据,而且加上判重,优化不好也会超时。
我们想判重能用什么方法,对于数字的判重我们可以用一个visit数组判断,对于路劲呢,没错我们能用map来判断,下面就是最后AC题的代码。

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int maxn=30;
const int ax[4]={1,0,0,-1};
const int ay[4]={0,1,-1,0};
int n,ans;
char maze[maxn][maxn];
map<string,int>t;
map<string,int>T[maxn];
void dfs1(int x,int y,string a) {//第一遍搜索
	if(x+y==n+1) {
		T[x][a]=1;
		return ;
	}
	for(int i=0;i<2;i++)
		dfs1(x+ax[i],y+ay[i],a+maze[x+ax[i]][y+ay[i]]);
}
void dfs2(int x,int y,string b) {//第二遍搜索加判重。
	if(x+y==n+1) {
		if(T[x][b]==1&&!t[b]) {如果t[b]不为零则代表之前有路径是b的但是通过的是不同的点,T[x][b]来判断在x位置的点是否是路径上半与现在搜索的一样。
			ans++;
			t[b]=1;//标记上已近存在答案,判重,
		}
		return ;
	}
	for(int i=2;i<4;i++)
		dfs2(x+ax[i],y+ay[i],b+maze[x+ax[i]][y+ay[i]]);
}
int main() {
	cin>>n;
	ans=0;
	for(int i=1;i<=n;i++) 
		for(int j=1;j<=n;j++)
			cin>>maze[i][j];
	string a;
	a+=maze[1][1];
	dfs1(1,1,a);
	string b;
	b+=maze[n][n];
	dfs2(n,n,b);
	cout<<ans<<endl;
	return 0;
}

或许有人会问为什么T数组只有一维,为什么只要判断x不用判断y,应为这里x+y==n+1,所有的点都落在的对角线上。

猜你喜欢

转载自blog.csdn.net/weixin_45483201/article/details/104255693