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';
}