[CF 1006F]Xor Paths
这道题如果范围在10以内的话,可以用普通的\(bfs\)搜过,但是因为范围到达\(20\),普通的搜索会炸.因此需要换个算法.
因为起点为固定点\((1,1)\),重点也为固定点\((n,m)\),且到达终点时的"异或和"为固定值\(k\),因此可以考虑使用"双向广度优先搜索".
先设定一条"终点线",正搜反搜到达终点线时都停止.如果在同一个点有重合的状态,则可以统计答案.
因为正反都只搜大约一半,因此与搜索一个\(n \leq 10\) 的矩阵相当,不会TLE
#include <iostream>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
const int MAXN = 20+5;
struct State{
int x,y;
LL val;
State(int a=0,int b=0,LL v=0):x(a),y(b),val(v){}
};
int n,m,mid;
LL a[MAXN][MAXN],k;
map<LL,int>MAP[MAXN << 1];
bool valid(int x,int y)
{
return x>=1 && x<=n && y>=1 && y<=m;
}
int main()
{
cin >> n >> m >> k;
mid = (n+m+2) >> 1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) cin >> a[i][j];
LL ans = 0;
queue<State>q;
q.push(State(1,1,a[1][1]));
while(!q.empty())
{
State u = q.front(); q.pop();
int x = u.x,y = u.y;
LL val = u.val;
if(x + y == mid)
{
if(MAP[x].count(val)) ++MAP[x][val];
else MAP[x][val] = 1;
}
else
{
if(valid(x+1,y)) q.push(State(x+1,y,val^a[x+1][y]));
if(valid(x,y+1)) q.push(State(x,y+1,val^a[x][y+1]));
}
}
q.push(State(n,m,k));
while(!q.empty())
{
State u = q.front(); q.pop();
int x = u.x,y = u.y;
LL val = u.val;
if(x + y == mid) ans += MAP[x][val];
else
{
if(valid(x-1,y)) q.push(State(x-1,y,val^a[x][y]));
if(valid(x,y-1)) q.push(State(x,y-1,val^a[x][y]));
}
}
cout << ans << endl;
}
调试了两天原来是把一个减号写成了加号...