Codeforces ~ 1006F ~ Xor-Paths(dfs + 中途相遇法)

题意

问你从(1,1)到(n,m)异或和为 k 的路径有多少条?只能向右和向下走。

思路

我们从(1,1)到(n,m)直接爆搜会超时,我们可以从前往后搜一半记录走到横坐标为x的点的时候路径有多少条,从后往前搜一半,终点a[x][y]会被两条路都统计进去,在^a[x][y]就好了,统计答案即可。

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 25;
const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};
typedef long long LL;
int n, m;
LL k, a[MAXN][MAXN], ans;
unordered_map<LL, LL> mp[MAXN];
void dfs_pre(int x, int y, LL sum)
{
    if (x+y == (n+m-2)/2) { mp[x][sum]++; return ; }
    for (int i = 0; i < 2; i++)
    {
        int X = x+dx[i], Y = y+dy[i];
        if (X >= 0 && Y >= 0 && X < n && Y < m)
            dfs_pre(X, Y, sum^a[X][Y]);
    }
}
void dfs_suf(int x, int y, LL sum)
{
    if (x+y == (n+m-2)/2) { ans += mp[x][sum^k^a[x][y]]; return ; }
    for (int i = 2; i < 4; i++)
    {
        int X = x+dx[i], Y = y+dy[i];
        if (X >= 0 && Y >= 0 && X < n && Y < m)
            dfs_suf(X, Y, sum^a[X][Y]);
    }
}
int main()
{
    scanf("%d%d%lld", &n, &m, &k);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            scanf("%lld", &a[i][j]);
    dfs_pre(0, 0, a[0][0]);
    dfs_suf(n-1, m-1, a[n-1][m-1]);
    printf("%lld", ans);
    return 0;
}
/*
3 3 11
2 1 5
7 10 0
12 6 4
*/

猜你喜欢

转载自blog.csdn.net/zscdst/article/details/81078978