AtCoder Beginner Contest 271 F - XOR on Grid Path(meet in the middle)

题意:

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

优化:

用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());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值