[cdoj1380] Xiper的奇妙历险(3) (八数码问题 bfs + 预处理)

快要NOIP 2016 了,现在已经停课集训了。计划用10天来复习以前学习过的所有内容。首先就是搜索。

八数码是一道很经典的搜索题,普通的bfs就可求出。为了优化效率,我曾经用过康托展开来优化空间,甚至还用过A*来优化时间。不过这道题懒得写了,就一个普普通通的bfs,再加上一个stl 的map就水过了。

首先题目要求有多达10000组数据,依次搜索肯定是不行的,我试过用A*来写,第2组数据就会T掉,所以我们考虑用一个预处理。从末尾状态搜索所有可行的状态,并用一个map来存储答案。然后就很好写了。

 

不过最智障的是,我用getchar读入数据,手测数据都对,交上去wa了无数次,改了快一晚上才发现是读入挂了。辣鸡getchar

 

 1 #include <iostream>
 2 #include <map>
 3 #include <queue>
 4 #include <cstdio> 
 5 using namespace std;
 6 typedef pair <int ,int> pis;
 7 #define OK(a,b) (a < 3 && a >= 0 && b < 3 && b >= 0)
 8 
 9 int t;
10 map <long long, int > MAP;
11 queue <pis > q;
12 
13 int mx[] = {1,-1,0,0};
14 int my[] = {0,0,-1,1};
15 
16 inline int E(int x){return x==0 ? 1 : 10 * E(x-1);}
17 
18 inline void bfs(){
19     int u = 123456780;
20     int p;
21     MAP[u] = 1;
22     q.push(make_pair(u,8));
23     while(!q.empty()){
24         u = q.front().first; p = q.front().second;q.pop();
25         int x = p / 3, y = p % 3;
26         for(int i = 0;i < 4;i++){
27             int nx = x + mx[i];
28             int ny = y + my[i];
29             if(OK(nx,ny)){
30                 int nu = u;
31                 int xx = (nu % E(9-(nx * 3 + ny))) / E(8-(nx * 3 + ny));
32                 nu -= xx * E(8-(nx * 3 + ny));
33                 nu += xx * E(8-p);
34                 if(!MAP[nu]){
35                     MAP[nu] = MAP[u] + 1;
36                     q.push(make_pair(nu,nx*3+ny));
37                 }
38             }
39         }
40     }
41     
42 }
43 
44 int main(){
45     bfs();
46     
47     scanf("%d",&t);
48     char s[9];
49     while(t--){
50         int m = 0;
51         for(int i = 0;i < 9;i++){
52             scanf("%s",s);
53             m = m * 10 + (s[0] == 'x' ? 0 : (s[0] - '0'));
54         }
55         printf("%d\n",MAP[m] - 1);
56     }
57     
58     return 0; 
59 }
View Code

 

转载于:https://www.cnblogs.com/ZegWe/p/5940397.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值