[CF 1006F]Xor Paths

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

调试了两天原来是把一个减号写成了加号...

posted @ 2018-11-08 15:51  昤昽  阅读(175)  评论(0编辑  收藏  举报