Loading

ABC 271 F - XOR on Grid Path(搜索 meet in the mid)

ABC 271 F - XOR on Grid Path

题意:

​ 给出20 * 20的地图,每个点上都有一个点权,保证为正整数。请问从(1, 1)走到(n, n)且路径上所有点权异或和为0的路径有多少条。

思路:

​ 本题利用了meet in the mid的思想。因为是(1, 1)到(n, n),所以一定会在某个中间的地方相遇。

​ 走到某点(x, y)会有很多种路径,以及很多个不同的异或和值。因为从(1, 1)走到(n, n)一共是2 * n步。

​ 我们预处理从(1, 1)只向右下走,走到(x, y),且步数为n的时候停止,并将异或和加入\(mp[x][y][val] ++\)

​ 然后再从(n, n)只向左上走,走到(x, y)的时候,如果此时的异或和有这样的值存在\(mp[x][y]\),就把方案数加上。

​ 这样做的时间复杂度是2 * C(20, 10),还有一个map的log复杂度。(用umap可能被卡到O(n),在CF慎用)。

实现:

\(map<int, int> [x][y]\)为走到(x, y)的时候,他的不同的值和其方案数。

int n;
int c[22][22];
map<int, int> mp[22][22];
int res = 0;

void dfs1(int x, int y, int step, int sum)
{
    if (step == n)
    {
        mp[x][y][sum ^ c[x][y]]++; //最后一步
        return;
    }
    if (x + 1 <= n)
        dfs1(x + 1, y, step + 1, sum ^ c[x][y]);
    if (y + 1 <= n)
        dfs1(x, y + 1, step + 1, sum ^ c[x][y]);
}

void dfs2(int x, int y, int step, int sum)
{
    if (step == n)
    {
        res += mp[x][y][sum];
        return;
    }
    if (x - 1 >= 1)
        dfs2(x - 1, y, step + 1, sum ^ c[x][y]);
    if (y - 1 >= 1)
        dfs2(x, y - 1, step + 1, sum ^ c[x][y]);
}

signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            cin >> c[i][j];

    dfs1(1, 1, 1, 0);
    dfs2(n, n, 1, 0);
    cout << res << '\n';
}
posted @ 2022-10-08 21:15  DM11  阅读(36)  评论(0编辑  收藏  举报