【Codeforces1006F】Xor-Paths

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


 

%%%dalao

dalao们都说这是道模板题,呵呵,确实,但双向广搜(此题深搜也可以)写过的人比较少。

这道题可以考虑直接暴力,显然并不能A掉,因为每次向右下扩展一层,状态数增长不超过2倍,复杂度是O(2^(m+n))的。

而如果采用双向广搜,从左上结点向下扩展至中心线,再从右下结点向上扩展至中心线,结果的重叠部分就是答案。

上述做法有个好玩的名字——meet in the middle。

关于实现细节,注意以下几点:

1、部分数据用long long,long long可以到2^63-1,int可以到2^31-1,因为有些数据是可以达到10^18的,所以要使用long long,包括ans。

2、我们定义状态为结点的坐标及已得到(或得到)的异或和。

3、取中心线时,要注意适当移动一下,使得其更靠近中心。

4、第一次和第二次广搜是略有区别的。。。包括状态的扩展。

5、扩展状态时注意加条件,因为n,m不一定相等,所以要避免扩展的状态出界。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<map>
 4 #include<queue>
 5 using namespace std;
 6 typedef long long ll;
 7 const int mmax=25;
 8 int n,m;
 9 ll k,mt[mmax][mmax],ans;
10 struct node {
11     int x,y;
12     ll num;
13     node(int x,int y,ll num):x(x),y(y),num(num) {}
14 };
15 queue<node> q;
16 map<ll,int> M[mmax];
17 int main() {
18     ios::sync_with_stdio(false);
19     cin.tie();cout.tie();
20     cin>>n>>m>>k;
21     for(int i=1;i<=n;++i)
22         for(int j=1;j<=m;++j) cin>>mt[i][j];
23     int mid=(n+m+2)/2;
24     q.push(node(1,1,mt[1][1]));
25     while(!q.empty()) {
26         int x=q.front().x,y=q.front().y;
27         ll num=q.front().num;
28         q.pop();
29         if(x+y==mid) {
30             if(!M[x].count(num)) M[x].insert(pair<ll,int>(num,1));
31             else ++M[x][num];
32         }
33         else {
34             if(y<m) q.push(node(x,y+1,num^mt[x][y+1]));
35             if(x<n) q.push(node(x+1,y,num^mt[x+1][y]));
36         }
37     }
38     q.push(node(n,m,k));
39     while(!q.empty()) {
40         int x=q.front().x,y=q.front().y;
41         ll num=q.front().num;
42         q.pop();
43         if(x+y==mid) ans+=M[x][num];
44         else {
45             if(y>1) q.push(node(x,y-1,num^mt[x][y]));
46             if(x>1) q.push(node(x-1,y,num^mt[x][y]));
47         }
48     }
49     cout<<ans;
50     return 0;
51 }
AC代码

 

posted @ 2018-10-02 06:25  Mr^Kevin  阅读(134)  评论(0编辑  收藏  举报