题意:
有多少种异或路径,使得异或路径和为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−1n+n-1n+n−1。
如果暴力搜索,搜索树的深度 即为 n+n−1n+n-1n+n−1,每次有两种选法,形似二叉树。
所以暴力的复杂度约为 2n+n−12^{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());
}
}

本文介绍了一种通过Meet-in-the-Middle技术优化暴力搜索的方法,用于寻找从(1,1)到(n,n)所有可能路径中异或和为0的路径数量。提供了详细的算法思路及Java实现。

383

被折叠的 条评论
为什么被折叠?



