标签:dba algorithm eof i++ cst isp vector 解法 双向
进化史,一种比一种长,一种比一种快。不过第三种似乎还不是最终形态。
第一种,傻逼级迭代加深。
去年十一月写的,那时候刚刚学迭代加深,敲了一个钟头才敲完,codevs上直接过,就没太管,觉得这是个水题。实际上呢,看后文。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 int sx,sy,lim,a[4][4],t[4][4]={{},{0,1,2,3},{0,8,0,4},{0,7,6,5}},ax[]={-1,1,0,0},ay[]={0,0,-1,1}; 7 int f(){ 8 int cnt=0; 9 for(int i=1;i<=3;i++) 10 for(int j=1;j<=3;j++) 11 cnt+=a[i][j]!=t[i][j]; 12 return cnt; 13 } 14 void dfs(int x,int y,int s){ 15 if(memcmp(a,t,sizeof(a))==0){cout<<s<<endl;exit(0);} 16 if(s+f()>lim)return; 17 for(int k=0;k<4;k++){ 18 int nx=x+ax[k],ny=y+ay[k]; 19 if(nx<1||ny<1||nx>3||ny>3)continue; 20 swap(a[nx][ny],a[x][y]); 21 dfs(nx,ny,s+1); 22 swap(a[nx][ny],a[x][y]); 23 } 24 } 25 int main(){ 26 for(int i=1;i<=3;i++) 27 for(int j=1;j<=3;j++) 28 if((a[i][j]=getchar()-‘0‘)==0)sx=i,sy=j; 29 for(lim=1;lim<=100;lim++)dfs(sx,sy,0); 30 return 0; 31 }
这种在洛谷上八十分,加上超时的第八和第十两个点,总用时2422。
第二种,基础的单向广搜。
前几天才听说原来八数码有多种解法,而且codevs上的数据极弱无比。我不信邪地把去年在codevs已经AC的代码提交在洛谷上,结果已经提到了。于是我决定花几天重打一遍,迭代加深再优化下去我一时还想不大出来,所以就先弄了下面这个单向广搜。
1 #include<map> 2 #include<set> 3 #include<queue> 4 #include<cmath> 5 #include<cstdio> 6 #include<vector> 7 #include<string> 8 #include<cstring> 9 #include<iostream> 10 #include<algorithm> 11 using namespace std; 12 const int ax[]={0,3,-1,1,-3}; 13 const bool av[8][16]={{},{1,1,1,1,1,1,0,0,0},{0,1,1,0,1,1,0,1,1}, 14 {1,1,0,1,1,0,1,1,0},{0,0,0,1,1,1,1,1,1}}; 15 16 struct bd{ 17 string s; 18 int sp,pth; 19 }st; 20 queue<bd> q; 21 map<string,bool> tb; 22 bool dn; 23 int main(){ 24 bd tg; 25 tg.s="123804765"; 26 cin>>st.s; 27 for(int i=0;i<st.s.size();i++)if(st.s[i]==‘0‘){st.sp=i;break;} 28 st.pth=0; 29 tb[st.s]=true; 30 q.push(st); 31 while(!dn&&!q.empty()){ 32 bd x=q.front();q.pop(); 33 if(x.s==tg.s){ 34 cout<<x.pth<<endl; 35 return 0; 36 } 37 for(int i=1;i<=4;i++){ 38 if(!av[i][x.sp])continue; 39 bd nx=x;nx.sp+=ax[i];nx.pth=x.pth+1; 40 swap(nx.s[nx.sp],nx.s[x.sp]); 41 42 if(!tb[nx.s]){ 43 q.push(nx); 44 tb[nx.s]=true; 45 } 46 } 47 } 48 49 return 0; 50 }
此代码在洛谷上总用时2165。
第三种,稍加改良的双向广搜
我目前也只想打到这个程度了,上面那个单向是前天敲的,这个第三种半小时前才正式完工。用时比我预想的“理论上比单向减少一半”更惊喜。
1 #include<map> 2 #include<set> 3 #include<queue> 4 #include<cmath> 5 #include<cstdio> 6 #include<vector> 7 #include<string> 8 #include<cstring> 9 #include<iostream> 10 #include<algorithm> 11 using namespace std; 12 const int ax[]={0,3,-1,1,-3}; 13 const bool av[8][16]={{},{1,1,1,1,1,1,0,0,0},{0,1,1,0,1,1,0,1,1},{1,1,0,1,1,0,1,1,0},{0,0,0,1,1,1,1,1,1}}; 14 struct bd{ 15 string s; 16 int sp,pth; 17 }st; 18 queue<bd> q1,q2; 19 map<string,int> tb1,tb2; 20 int main(){ 21 bd tg; 22 tg.s="123804765";tg.sp=4;tg.pth=1; 23 tb2[tg.s]=1; 24 q2.push(tg); 25 cin>>st.s; 26 for(int i=0;i<st.s.size();i++)if(st.s[i]==‘0‘){st.sp=i;break;} 27 st.pth=1; 28 tb1[st.s]=1; 29 q1.push(st); 30 while(!q2.empty()&&!q1.empty()){ 31 bd x1=q1.front(),x2=q2.front();q1.pop();q2.pop(); 32 if(tb2[x1.s]){ 33 cout<<x1.pth+tb2[x1.s]-2<<endl; 34 return 0; 35 } 36 if(tb1[x2.s]){ 37 cout<<x2.pth+tb1[x2.s]-2<<endl; 38 return 0; 39 } 40 for(int i=1;i<=4;i++){ 41 if(av[i][x1.sp]){ 42 bd nx=x1; 43 nx.sp+=ax[i];nx.pth=x1.pth+1; 44 swap(nx.s[nx.sp],nx.s[x1.sp]); 45 if(!tb1[nx.s]){ 46 q1.push(nx); 47 tb1[nx.s]=nx.pth; 48 } 49 } 50 if(av[i][x2.sp]){ 51 bd nx=x2; 52 nx.sp+=ax[i];nx.pth=x2.pth+1; 53 swap(nx.s[nx.sp],nx.s[x2.sp]); 54 if(!tb2[nx.s]){ 55 q2.push(nx); 56 tb2[nx.s]=nx.pth; 57 } 58 } 59 } 60 } 61 return 0; 62 }
洛谷上总用时38。
标签:dba algorithm eof i++ cst isp vector 解法 双向
原文地址:http://www.cnblogs.com/duskfire/p/6777320.html