Codeforces Round #498 (Div. 3) F(异或,折半搜索)

https://codeforces.com/problemset/problem/1006/F
F. Xor-Paths
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
There is a rectangular grid of size n×m. Each cell has a number written on it; the number on the cell (i,j) is ai,j. Your task is to calculate the number of paths from the upper-left cell (1,1) to the bottom-right cell (n,m) meeting the following constraints:

You can move to the right or to the bottom only. Formally, from the cell (i,j) you may move to the cell (i,j+1) or to the cell (i+1,j). The target cell can’t be outside of the grid.
The xor of all the numbers on the path from the cell (1,1) to the cell (n,m) must be equal to k (xor operation is the bitwise exclusive OR, it is represented as ‘^’ in Java or C++ and “xor” in Pascal).
Find the number of such paths in the given grid.

Input
The first line of the input contains three integers n, m and k (1≤n,m≤20, 0≤k≤1018) — the height and the width of the grid, and the number k.

The next n lines contain m integers each, the j-th element in the i-th line is ai,j (0≤ai,j≤1018).

Output
Print one integer — the number of paths from (1,1) to (n,m) with xor sum equal to k.

Examples
inputCopy
3 3 11
2 1 5
7 10 0
12 6 4
outputCopy
3
inputCopy
3 4 2
1 3 3 3
0 3 3 2
3 0 1 1
outputCopy
5
inputCopy
3 4 1000000000000000000
1 3 3 3
0 3 3 2
3 0 1 1
outputCopy
0
Note
All the paths from the first example:

(1,1)→(2,1)→(3,1)→(3,2)→(3,3);
(1,1)→(2,1)→(2,2)→(2,3)→(3,3);
(1,1)→(1,2)→(2,2)→(3,2)→(3,3).
All the paths from the second example:

(1,1)→(2,1)→(3,1)→(3,2)→(3,3)→(3,4);
(1,1)→(2,1)→(2,2)→(3,2)→(3,3)→(3,4);
(1,1)→(2,1)→(2,2)→(2,3)→(2,4)→(3,4);
(1,1)→(1,2)→(2,2)→(2,3)→(3,3)→(3,4);
(1,1)→(1,2)→(1,3)→(2,3)→(3,3)→(3,4).
题意:从端点[1,1]走至端点[n,m],只能向右向下,每个点都带有一个数值,经过的路径数值全异或后等于k时,该路径符合要求。输出符合该条件的路径条数。
思路:1<=n,m<=20,纯dfs复杂度至2^(20+20),Tle,得用折半搜索

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 21;
int mp[N][N],n,m,k,ans;
map<int,int>dp[N][N];
bool check(int x,int y){
	if (x<=n&&x>=1&&y<=m&&y>=1) return 1;
	else return 0;
}
void dfs1(int x,int y,int sum){
	if(x + y - 1 == n){
		dp[x][y][sum]++;
		return;
	}
	if(check(x,y+1)) dfs1(x,y+1,sum ^ mp[x][y+1]);
	if(check(x+1,y)) dfs1(x+1,y,sum ^ mp[x+1][y]);
}
void dfs2(int x,int y,int sum){
	if(x + y - 1 == n){
		ans += dp[x][y][sum ^ k ^ mp[x][y]];
		return;
	}
	if(check(x,y-1)) dfs2(x,y-1,sum ^ mp[x][y-1]);
	if(check(x-1,y)) dfs2(x-1,y,sum ^ mp[x-1][y]);
}

signed main()
{
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
		{
			cin >> mp[i][j];
		}
	dfs1(1,1,mp[1][1]);
	dfs2(n,m,mp[n][m]);
	cout << ans << endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值