• 对称迷宫


    描述

    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,所有的点都落在的对角线上。

  • 相关阅读:
    Jersey的异常处理
    REST响应处理
    jersey REST的接口简述
    Firebird 同一字段的多行合并为一行
    Firebird/InterBase内置函数使用说明
    发布FireBird数据库所需要DLL文件
    unidac连接FireBird数据库
    打开与关闭Linux防火墙
    Linux FTP 命令
    Linux 命令修改系统时间
  • 原文地址:https://www.cnblogs.com/lifehappy/p/12601201.html
Copyright © 2020-2023  润新知