1. 程式人生 > >【Codeforces1006F】Xor-Paths

【Codeforces1006F】Xor-Paths

hid clu 分數 def pty else false names out

題目鏈接: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代碼

【Codeforces1006F】Xor-Paths