标签:
Portal: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1345
http://codeforces.com/gym/100803/attachments A题
好题!
坑不多,切入比较难
一开始的想法是暴力,由于求得是最小解且此图太大无边界,所以不能DFS,首先想到BFS
解法1 BFS+STL queue
1 #include<iostream> 2 #include<algorithm> 3 #include<set> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cmath> 7 #include<queue> 8 using namespace std; 9 #define FOR(i,j,k) for(int i=j;i<=k;i++) 10 #define FORD(i,j,k) for(int i=j;i>=k;i--) 11 #define LL long long 12 #define SZ(x) x.size() 13 int vis[40000]; 14 int x,k,n,m,s,ans,start,end1,end2,dight; 15 int bfs() 16 { 17 queue<int> q1,q2; 18 q1.push(start); 19 q2.push(1); 20 vis[start]=1; 21 while(q1.front()!=end1&&q1.front()!=end2) 22 { 23 int fr=q1.front(); 24 int fv=q2.front(); 25 FOR(i,0,n-2) 26 { 27 if((fr&(1<<i))&&!(fr&(1<<(i+1)))) 28 { 29 ans=fr+(1<<i); 30 if(!vis[ans]) {vis[ans]=1;q1.push(ans);q2.push(fv+1);} 31 } 32 else if(!(fr&(1<<i))&&(fr&(1<<(i+1)))) 33 { 34 ans=fr-(1<<i); 35 if(!vis[ans]) {vis[ans]=1;q1.push(ans);q2.push(fv+1);} 36 } 37 } 38 q1.pop(); 39 q2.pop(); 40 } 41 return q2.front()-1; 42 } 43 int main() 44 { 45 cin>>n>>m; 46 dight=1; 47 FORD(i,n-1,0) 48 { 49 cin>>x; 50 start+=x<<i; 51 } 52 int c=n; 53 FOR(i,1,m) 54 { 55 cin>>x; 56 FOR(j,1,x) 57 { 58 c--; 59 end1+=dight<<c; 60 end2+=(1-dight)<<c; 61 } 62 dight^=1; 63 } 64 cout<<bfs()<<endl; 65 return 0; 66 }
解法2 BFS+手写queue
1 #include<iostream> 2 #include<algorithm> 3 #include<set> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cmath> 7 //#include<queue> 8 using namespace std; 9 #define FOR(i,j,k) for(int i=j;i<=k;i++) 10 #define FORD(i,j,k) for(int i=j;i>=k;i--) 11 #define LL long long 12 #define SZ(x) x.size() 13 int vis[40000]; 14 int x,k,n,m,s,ans,start,end1,end2,dight; 15 16 int bfs() 17 { 18 int q1[40000];int L1=1;int R1=0; 19 int q2[40000];int L2=1;int R2=0; 20 q1[++R1]=start; 21 q2[++R2]=1; 22 vis[start]=1; 23 while(q1[L1]!=end1&&q1[L1]!=end2) 24 { 25 int fr=q1[L1]; 26 int fv=q2[L2]; 27 FOR(i,0,n-2) 28 { 29 if((fr&(1<<i))&&!(fr&(1<<(i+1)))) 30 { 31 ans=fr+(1<<i); 32 if(!vis[ans]) {vis[ans]=1;q1[++R1]=ans;q2[++R2]=fv+1;} 33 } 34 else if(!(fr&(1<<i))&&(fr&(1<<(i+1)))) 35 { 36 ans=fr-(1<<i); 37 if(!vis[ans]) {vis[ans]=1;q1[++R1]=ans;q2[++R2]=fv+1;} 38 } 39 } 40 L1++; 41 L2++; 42 } 43 return q2[L2]-1; 44 } 45 int main() 46 { 47 cin>>n>>m; 48 dight=1; 49 FORD(i,n-1,0) 50 { 51 cin>>x; 52 start+=x<<i; 53 } 54 int c=n; 55 FOR(i,1,m) 56 { 57 cin>>x; 58 FOR(j,1,x) 59 { 60 c--; 61 end1+=dight<<c; 62 end2+=(1-dight)<<c; 63 } 64 dight^=1; 65 } 66 cout<<bfs()<<endl; 67 return 0; 68 }
比较同样情况下STL的queue和手写的queue,我发现STL的queue内存比手写的多了4KB
这是个严重的问题,因为STL经常pop元素,是动态的,它的内存一定较小,但即便在手写的queue固定大小为8e5个int的情况下,仍然多4KB,即1e3个int
STL的queue在此题理论上能够最多有16384个元素,所以事实上同等长度的queue所用内存相当于3到4倍同等int
所以,我们应该谨慎使用STL,为保险起见,用queue时数据输入的极限容量不得多于1e7,即1/10int在32768KB下容量左右
在解法1/2的代码中使用了位运算的黑科技
FORD(i,n-1,0) { cin>>x; start+=x<<i; } int c=n; FOR(i,1,m) { cin>>x; FOR(j,1,x) { c--; end1+=dight<<c; end2+=(1-dight)<<c; } dight^=1; } /// if((fr&(1<<i))&&!(fr&(1<<(i+1)))) { ans=fr+(1<<i); if(!vis[ans]) {vis[ans]=1;q1[++R1]=ans;q2[++R2]=fv+1;} } else if(!(fr&(1<<i))&&(fr&(1<<(i+1)))) { ans=fr-(1<<i); if(!vis[ans]) {vis[ans]=1;q1[++R1]=ans;q2[++R2]=fv+1;} }
其中(fr&(1<<i))&&!(fr&(1<<(i+1)))最妙
fr&(1<<i)表示判断fr的二进制表示中第i位是否为1(利用了c++非0为真的机制)
这样使用黑科技的原因是这题中交换相同的二进制位是没有意义
所以仅仅交换01和10来产生当前数字的邻居
解法3(2) 贪心
coderforces Gym 100803A/Aizu 1345/CSU 1536/UVALive 6832 Bit String Reordering(未完)
标签:
原文地址:http://www.cnblogs.com/mukoiaoi/p/5651018.html