题意:
有多少种异或路径,使得异或路径和为0.
从 (1,1) 到 (n,n)。
每次只能
(
x
,
y
)
−
>
(
x
+
1
,
y
)
(x,y)->(x+1,y)
(x,y)−>(x+1,y) 或者
(
x
,
y
)
−
>
(
x
,
y
+
1
)
(x,y)->(x,y+1)
(x,y)−>(x,y+1)
思路:
时间复杂度分析:
路径长度为
n
+
n
−
1
n+n-1
n+n−1。
如果暴力搜索,搜索树的深度 即为
n
+
n
−
1
n+n-1
n+n−1,每次有两种选法,形似二叉树。
所以暴力的复杂度约为
2
n
+
n
−
1
2^{n+n-1}
2n+n−1
优化:
用meet in the middle。
我们分别进行两次dfs。
- 第一次dfs从 ( 1 , 1 ) (1,1) (1,1)搜到对角线
- 第二次dfs从 ( n , n ) (n,n) (n,n)搜到对角线,统计第一次dfs记录的答案。
AC (Java)
package com.hgs.atcoder.abc.contest271.f;
import java.io.*;
import java.util.*;
/**
* @author 12503
* @version 1.0
* Create by 2022/10/1 21:19
*/
public class Main {
static int n;
static int a[][];
static long ans = 0;
static Map<Integer,Integer> vis[][];
static void dfs1(int x, int y, int val){
if(x + y == n + 1) {
val = val^a[x][y];
int cnt = 0;
if(vis[x][y].get(val) != null) {
cnt = vis[x][y].get(val) + 1;
vis[x][y].remove(val);
}else cnt = 1;
vis[x][y].put(val,cnt);
return ;
}
if(x + 1 <= n) {
dfs1(x + 1,y, val^a[x][y]);
}
if(y + 1 <= n){
dfs1(x,y+1, val^a[x][y]);
}
}
static void dfs2(int x, int y, int val){
if(x + y == n + 1) {
val = val;
if(vis[x][y].get(val) != null) {
ans += vis[x][y].get(val);
}
return ;
}
if(x -1 >= 1) {
dfs2(x - 1,y, val^a[x][y]);
}
if(y -1 >= 1){
dfs2(x,y-1, val^a[x][y]);
}
}
public static void main(String[] args) throws IOException {
FastScanner cin = new FastScanner(System.in);
PrintWriter cout = new PrintWriter(System.out);
n = cin.nextInt();
a = new int[n+1][n+1];
vis = new HashMap[n+1][n+1];
for(int i = 1; i <= n; i ++ ) for(int j = 1; j <= n; j ++ ) {
vis[i][j] = new HashMap<>();
}
for(int i = 1; i <= n; i ++ ) for(int j = 1; j <= n; j ++ ) {
a[i][j] = cin.nextInt();
}
dfs1(1,1,0);
dfs2(n,n, 0);
cout.print(ans);
cout.close();
}
}
class FastScanner {
BufferedReader br;
StringTokenizer st = new StringTokenizer("");
public FastScanner(InputStream s) {
br = new BufferedReader(new InputStreamReader(s));
}
public FastScanner(String s) throws FileNotFoundException {
br = new BufferedReader(new FileReader(new File(s)));
}
public String next() throws IOException {
if (!st.hasMoreTokens())
st = new StringTokenizer(br.readLine());
return st.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public long nextLong() throws IOException {
return Long.parseLong(next());
}
public double nextDouble() throws IOException {
return Double.parseDouble(next());
}
}