第十场 hdu 6171 Admiral(双向bfs找交点)

Posted Wally的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十场 hdu 6171 Admiral(双向bfs找交点)相关的知识,希望对你有一定的参考价值。

http://acm.hdu.edu.cn/showproblem.php?pid=6171

 

题目大意:给你一个塔形的数据共有1个0、2个1、3个2、4个3、5个4、6个5.你能够把0这个数据和它的上、左上、下、右下的数据进行交换。问在最多20步内能否变成按顺序排列的塔形数据?如果能输出最小步数,否则输出-1.

解题思路:因为有20步4个方向所以暴力搜索肯定是不可以的。因为有起点有终点所以我们能分两部分去搜索。但是这样搜索的话还是要去找枚举相遇的,这样的话还是会超时的,所以我们在搜索的同时还要找出来一下相遇的最少步数。
我们应该用队列去完成宽搜并用map去存储到达该状态的最少步数,并且起点和终点状态最多只能向前枚举10次以减少时间复杂度。如果在某个状态枚举的情况相遇了则说明已经找到了最少的步数。
我们应该对给出的状态是不是起点状态进行特判,找到最少步数为0的情况。

 

AC代码:

技术分享
  1 #include <iostream>
  2 #include<bits/stdc++.h>
  3 //if(~i)//当i不是-1时满足条件
  4 using namespace std;
  5 queue<string>que;
  6 map<string,int>mp;
  7 int up[]= {-1,0,-1,1,2,-1,3,4,5,-1,6,7,8,9,-1,10,11,12,13,14,-1};
  8 int upleft[]= {-1,-1,0,-1,1,2,-1,3,4,5,-1,6,7,8,9,-1,10,11,12,13,14};
  9 int down[]= {1,3,4,6,7,8,10,11,12,13,15,16,17,18,19,-1,-1,-1,-1,-1,-1};
 10 int downright[]= {2,4,5,7,8,9,11,12,13,14,16,17,18,19,20,-1,-1,-1,-1,-1,-1};
 11 string ori="011222333344444555555";
 12 
 13 int solve(string next,string now,int nextpos,int pos)
 14 {
 15     if(~nextpos)
 16     {
 17         swap(next[pos],next[nextpos]);
 18         next[21]=nextpos/10+0;
 19         next[22]=nextpos%10+0;
 20         int cnt1=mp[next];
 21         int cnt2=mp[now];
 22         if(!cnt1)
 23         {
 24             mp[next]=mp[now]+1;
 25             que.push(next);
 26         }
 27         else if((cnt1>=20&&cnt2<=11)||(cnt2>=20&&cnt1<=11))
 28          return cnt1+cnt2-20;
 29         swap(next[pos],next[nextpos]);
 30     }
 31     return 0;
 32 }
 33 int dfs(string s)
 34 {
 35     int index;
 36     while(!que.empty())
 37         que.pop();
 38     mp.clear();
 39     for(int i=0; i<21; i++)
 40     {
 41         if(s[i]==0)
 42         {
 43             index=i;
 44             break;
 45         }
 46     }
 47     char st[5];
 48     st[0]=index/10+0;
 49     st[1]=index%10+0;
 50     st[2]=\0;
 51     que.push(s+st);
 52     que.push(ori+"00");
 53     mp[s+st]=20;
 54     mp[ori+"00"]=1;
 55     while(!que.empty())
 56     {
 57         string now=que.front();
 58         que.pop();
 59         int num=mp[now];
 60         if(num==11||num==30)
 61             continue;
 62         int pos=(now[21]-0)*10+(now[22]-0);
 63         int nextpos=up[pos];
 64         string next=now;
 65         int ans=solve(next,now,nextpos,pos);
 66         if(ans)
 67             return ans;
 68         nextpos=upleft[pos];
 69         ans=solve(next,now,nextpos,pos);
 70         if(ans)
 71             return ans;
 72         nextpos=down[pos];
 73         ans=solve(next,now,nextpos,pos);
 74         if(ans)
 75             return ans;
 76         nextpos=downright[pos];
 77         ans=solve(next,now,nextpos,pos);
 78         if(ans)
 79             return ans;
 80     }
 81     return -1;
 82 }
 83 int main()
 84 {
 85     int t;
 86     //freopen("1001.in","r",stdin);
 87     scanf("%d",&t);
 88     while(t--)
 89     {
 90         string s="",st;
 91         for(int i=0; i<21; i++)
 92         {
 93             cin>>st;
 94             s+=st;
 95         }
 96         if(s==ori)
 97         {
 98             printf("0\n");
 99             continue;
100         }
101         int ans=dfs(s);
102         if(ans==-1)
103         printf("too difficult\n");
104         else
105         printf("%d\n",ans);
106     }
107     return 0;
108 }
View Code

 





以上是关于第十场 hdu 6171 Admiral(双向bfs找交点)的主要内容,如果未能解决你的问题,请参考以下文章

杂题总汇HDU多校赛第十场 Videos

第十场 hdu 6178 (bfs)

第十场 hdu 6172 Array Challenge(矩阵快速幂)

2018多校第十场 HDU 6430 线段树合并

2017多校Round10(hdu6171~hdu6181)

hdu 6171