[Codeforces]1006F Xor-Paths 双向dfs

题目链接http://codeforces.com/problemset/problem/1006/F

简而言之,一个m*n(20*20)的数组,每个点有个权值,从(1,1)出发,每次可以向下/右走一个格,取路径所有权值的异或和^,求有几条路使从起点到到(m,n)的时候异或和为K(1e18)。

第一反应是裸dp,然后发现dp[i][j][k] = dp[i-1][j][ k^map[i][j] ] + dp[i][j-1][ k^map[i][j] ]但是第三维度显然存不下。

然后想了想mn不大,用vector<pair<long long, long long>>试试,i*m+j标号,把转移的(k,time)对都存在数组里,使用完清空,MLE。然后想遍历vector如果有first相同的元素更新second, TLE。然后想想好像跟暴力也没啥大区别。

然后想用map<pair<pair<int, int >, long long > >或者map<pair<int, int>, map<long long> >,发现不会stl嵌套。

然后看了看大神的代码,dfs超时,但是只有一个双向搜索就能搞定,连剪纸都不太要,感觉自己十分愚蠢。异或是满足结合律的。而且这个搜索只要先搜一半再对比一半就ok了,连动态左一下右一下都不要。

meet-in-the-middle。对于这个二维数组,一端的扫描从(1,1)开始,到达x+y = *在从左下到右上的那条先作为中轴线停止,x+y固定,下标只需要知道x就能取得y,map<int>[long long]记录。然后从另一端找过来,也是到了中轴线就可以判断次数。这样极限条件下到达中线时两边搜索层数都在10-20层,时间复杂度很够用。

特别注意一下中线位置的x+y应该等于多少的细节问题。

 

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 22;
long long a[MAXN][MAXN];
int n, m;
long long KK, ans;
map<long long, long long>mp[MAXN];
void dfs_down(int x, int y, long long maxn)
{
    if(x + y == (n + m - 1) / 2){mp[x][maxn]++;return;}
    if(x < n-1)dfs_down(x+1, y, maxn^a[x+1][y]);
    if(y < m-1)dfs_down(x, y+1, maxn^a[x][y+1]);
}

void dfs_up(int x, int y, long long maxn)
{
    if(x + y == (n + m - 1) / 2){
        if(mp[x].find(maxn ^ KK ^ a[x][y]) != mp[x].end()){
            ans += mp[x][maxn ^ KK ^ a[x][y]];
        }
        return;
    }
    if(x > 0)dfs_up(x-1, y, maxn^a[x-1][y]);
    if(y > 0)dfs_up(x, y-1, maxn^a[x][y-1]);

}

int main()
{
    scanf("%d%d%lld", &n, &m, &KK);
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            scanf("%lld", &a[i][j]);
        }
    }
    dfs_down(0,0, a[0][0]);
    dfs_up(n-1, m-1, a[n-1][m-1]);
    printf("%lld\n", ans);
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值