一、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();
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,