一、Problem
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
输入描述
- 第一行输入一个数 N NN,表示迷宫的大小。
接下来输入 N∗N N∗NN∗N 的字母迷宫
输出描述
- 输出对称路径的数量
输入
3 33
ABA ABAABA
BBB BBBBBB
ABA ABAABA
输出
2 22
评测用例规模与约定
- 对于 40% 的数据,2<=N<=11
对于 100% 的数据,2<=N<=18
二、Solution
方法一:暴搜(超时)
… 分
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
int N;
char[][] g;
Set<String> all;
boolean[][] vis;
final int[][] dir = { {1,0}, {0,1} };
void dfs(int x, int y, String p) {
if (x == N-1 && y == N-1 && check(p)) {
all.add(p);
return;
}
for (int k = 0; k < 2; k++) {
int tx = x + dir[k][0];
int ty = y + dir[k][1];
if (!inArea(tx, ty) || vis[tx][ty])
continue;
vis[tx][ty] = true;
dfs(tx, ty, p + g[tx][ty]);
vis[tx][ty] = false;
}
}
boolean check(String s) {
int l = 0, r = s.length()-1;
while (l < r) {
if (s.charAt(l++) != s.charAt(r--))
return false;
}
return true;
}
boolean inArea(int x, int y) {
return x < N && y < N;
}
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
all = new HashSet<>();
N = sc.nextInt();
g = new char[N][N];
vis = new boolean[N][N];
vis[0][0] = true;
for (int i = 0; i < N; i++) {
String s = sc.next();
for (int j = 0; j < N; j++)
g[i][j] = s.charAt(j);
}
dfs(0, 0, g[0][0] + "");
System.out.println(all.size());
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,
方法二:双向 dfs
- dfs1 从点 (0, 0) 遍历到矩阵上满足坐标和满足 x+y = N-1 的点,。
- dfs2 从点 (N-1, N-1) 矩阵上满足坐标和满足 x+y = N-1 的点,到达所述点之后,如果此时的路径和之前的保存的路径相同,那么 res++
流下 Java 超时的泪水:为什么…一样的逻辑,C++ 可以 A,看来非要我转 C++ 了,有缘再见 Java,你虐我太狠…
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
static class Solution {
int N;
char[][] g;
Set<String>[] ss;
Set<String> s2;
int res;
boolean[][] vis;
final int[][] dir = { {1,0}, {0,1} };
void dfs2(int x, int y, String p) {
if (x + y == N-1 && !s2.contains(p) && ss[x].contains(p)) {
res++;
s2.add(p);
return;
}
for (int k = 0; k < 2; k++) {
int tx = x - dir[k][0];
int ty = y - dir[k][1];
if (tx < 0 || ty < 0 || vis[tx][ty])
continue;
vis[tx][ty] = true;
dfs2(tx, ty, p + g[tx][ty]);
vis[tx][ty] = false;
}
}
void dfs1(int x, int y, String p) {
if (x + y == N-1) {
ss[x].add(p);
return;
}
for (int k = 0; k < 2; k++) {
int tx = x + dir[k][0];
int ty = y + dir[k][1];
if (tx >= N || ty >= N || vis[tx][ty])
continue;
vis[tx][ty] = true;
dfs1(tx, ty, p + g[tx][ty]);
vis[tx][ty] = false;
}
}
void init() {
Scanner sc = new Scanner(new BufferedInputStream(System.in));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
N = sc.nextInt();
g = new char[N][N];
vis = new boolean[N][N];
vis[0][0] = true;
ss = new HashSet[18+50];
s2 = new HashSet<>();
for (int i = 0; i < ss.length; i++) {
ss[i] = new HashSet<>();
}
for (int i = 0; i < N; i++) {
String s = sc.next();
for (int j = 0; j < N; j++)
g[i][j] = s.charAt(j);
}
dfs1(0, 0, g[0][0] + "");
dfs2(N-1, N-1, g[N-1][N-1] + "");
System.out.println(res);
}
}
public static void main(String[] args) throws IOException {
Solution s = new Solution();
s.init();
}
}
复杂度分析
- 时间复杂度: ,
- 空间复杂度: ,