题意:给你初始4个数字和目标4个数字,问是否能由初始经过变换到目标数字;
变换规则:每个数字可以加1(9+1=1)或减1(1-1=9),或交换相邻的数字(最左和最右不是相邻的)。
双向广搜:分别对初始和目标数字进行广搜,vis数组用1和2标记两种已搜索的数字,用mp数组记录状态的步数。
当从前往后搜可以到达2或从后往前搜可以到达1状态则就可以了。。。
#include<stdio.h> #include<string.h> #include<string> #include<queue> #include<map> #include<iostream> #include<algorithm> using namespace std; struct node { int a[4]; int step; }s,e; int vis[10001];//标记当前状态是否有走过(从前往后走为1,从后往前走为2,没有走过为0) int mp[10001];//标记走到当前状态的步数 int get_num(int c[]) { int n=0; for(int i=0;i<4;i++) { n*=10; n+=c[i]; } return n; } int bfs() { memset(vis,0,sizeof(vis)); memset(mp,0,sizeof(mp)); queue<node>p,q; int tmp; tmp=get_num(s.a); vis[tmp]=1; tmp=get_num(e.a); vis[tmp]=2; node u,v; p.push(s); q.push(e); while(!q.empty()||!p.empty()) { if(!p.empty()) { u=p.front(); p.pop(); for(int i=0;i<4;i++) { v=u; v.a[i]=u.a[i]+1;//+1 if(v.a[i]==10) v.a[i]=1; tmp=get_num(v.a); if(vis[tmp]==0)//从前往后没有走过 { v.step=u.step+1; mp[tmp]=v.step;//标记走到当前状态的步数 vis[tmp]=1; p.push(v); } else if(vis[tmp]==2)//从前往后与从后往前有交叉 return u.step+mp[tmp]+1; v.a[i]=u.a[i]-1;//-1 if(v.a[i]==0) v.a[i]=9; tmp=get_num(v.a); if(vis[tmp]==0) { v.step=u.step+1; mp[tmp]=v.step; vis[tmp]=1; p.push(v); } else if(vis[tmp]==2) return u.step+mp[tmp]+1; } for(int i=0;i<3;i++)//交换 { v=u; int k=v.a[i]; v.a[i]=v.a[i+1]; v.a[i+1]=k; tmp=get_num(v.a); if(vis[tmp]==0) { v.step=u.step+1; mp[tmp]=v.step; vis[tmp]=1; p.push(v); } else if(vis[tmp]==2) return u.step+mp[tmp]+1; } } if(!q.empty()) { u=q.front(); q.pop(); for(int i=0;i<4;i++) { v=u; v.a[i]=u.a[i]+1; if(v.a[i]==10) v.a[i]=1; tmp=get_num(v.a); if(vis[tmp]==0) { v.step=u.step+1; mp[tmp]=v.step; vis[tmp]=2; q.push(v); } else if(vis[tmp]==1)//从后往前与从前往后哟交叉 return u.step+mp[tmp]+1; v.a[i]=u.a[i]-1; if(v.a[i]==0) v.a[i]=9; tmp=get_num(v.a); if(vis[tmp]==0) { v.step=u.step+1; mp[tmp]=v.step; vis[tmp]=2; q.push(v); } else if(vis[tmp]==1) return u.step+mp[tmp]+1; } for(int i=0;i<3;i++) { v=u; int k=v.a[i]; v.a[i]=v.a[i+1]; v.a[i+1]=k; tmp=get_num(v.a); if(vis[tmp]==0) { v.step=u.step+1; mp[tmp]=v.step; vis[tmp]=2; q.push(v); } else if(vis[tmp]==1) return u.step+mp[tmp]+1; } } } } int main() { int t; scanf("%d",&t); while(t--) { char s1[10],s2[10]; scanf("%s%s",s1,s2); for(int i=0;i<4;i++) s.a[i]=s1[i]-'0'; for(int i=0;i<4;i++) e.a[i]=s2[i]-'0'; s.step=0; e.step=0; printf("%d\n",bfs()); } return 0; } /* 99 1221 1212 */
HDU 1195 Open the Lock (双向广搜)
时间: 2024-10-08 19:35:02