poj1915 -- Knight Moves

本文通过一个简单的广搜题目介绍了单广算法,并提出了利用双广算法进行优化的思路,详细阐述了双广算法的实现过程及其实验结果。

简单的广搜题目,单广能过,可以拿这题练习双广

单广:

View Code
 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 int n;
 5 int x1,y1,x2,y2;
 6 int array[2][8] = {{-1, -1, -2, -2, 2, 2, 1, 1},{-2, 2, 1, -1, 1, -1, 2, -2}};//表示马跳的8个方向
 7 int q[100000][3];
 8 bool h[310][310];
 9 void bfs()
10 {
11     int i,sd,ed;
12     int x,y,a,b,c;
13     sd = ed = 0;
14     q[ed][0] = x1;
15     q[ed][1] = y1;
16     q[ed][2] = 0;
17     h[x1][y1] = true;
18     ed++;
19     while(sd<ed)
20     {
21         a = q[sd][0];
22         b = q[sd][1];
23         c = q[sd][2];
24         if(a == x2 && b == y2) break;
25         for(i=0;i<8;i++)
26         {
27             x = a + array[0][i];
28             y = b + array[1][i];
29 
30             if(x >= 0 && x < n && y >= 0 && y < n)
31             {
32                 if(h[x][y]==false)
33                 {
34                     h[x][y] = true;
35                     q[ed][0] = x;
36                     q[ed][1] = y;
37                     q[ed][2] = c+1;
38                     ed++;
39                 }
40             }
41         }
42         sd++;
43     }
44     printf("%d\n",q[sd][2]);
45 }
46 
47 int main(void)
48 {
49     int t;
50     scanf("%d",&t);
51     while(t--)
52     {
53         scanf("%d",&n);
54         scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
55         memset(h,false,sizeof(h));
56         bfs();
57     }
58     return 0;
59 }

 

双广:

View Code
  1 #include <iostream>
  2 #include <queue>
  3 #include <cstdio>
  4 using namespace std;
  5 #define MAX 301
  6 struct Status   // 结构
  7 {
  8     int x,y;    //位置
  9     int vis;
 10 };
 11 int visited[MAX][MAX];//标记数组
 12 int dir[8][2]={{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2, 1}};
 13 int n,m;// n * m 矩形
 14 int ans[MAX][MAX];//标记前面走了多少步
 15 
 16 int result;//结果走的步数
 17 queue<Status> Q1;  // 正向队列
 18 queue<Status> Q2;  // 反向队列
 19 bool found; //标记成功找到
 20 Status s1,s2;//s1开始位置  s1结束位置
 21 
 22 void BFS_expand(queue<Status> &Q,bool flag)
 23 {  
 24     Status s,t;
 25     s=Q.front();  // 从队列中得到头结点s
 26     Q.pop();
 27     for(int i=0;i<8;i++)
 28     {
 29         t.x=s.x+dir[i][0];
 30         t.y=s.y+dir[i][1];    
 31         t.vis = s.vis + 1;
 32         if(t.x>=0 && t.x<n && t.y>=0 && t.y<m )  // 判是否越界            
 33         {
 34             if(flag)   // 在正向队列中判断
 35             {
 36                 if (visited[t.x][t.y]!=1) // 没在正向队列出现过
 37                 {
 38                     if(visited[t.x][t.y]==2)  // 该状态在反向队列中出现过
 39                     {    
 40                         found=true;
 41                         result = ans[t.x][t.y] + ans[s.x][s.y];
 42                         return;
 43                     }
 44                     ans[t.x][t.y] = t.vis;    
 45                     visited[t.x][t.y]=1;   // 标记为在在正向队列中
 46                     Q.push(t);  // 入队
 47                 }
 48             }
 49             else    // 在反向队列中判断
 50             {
 51                 if (visited[t.x][t.y]!=2) // 没在反向队列出现过
 52                 {
 53                     if(visited[t.x][t.y]==1)  // 该状态在正向向队列中出现过
 54                     {            
 55                         found=true;
 56                         result = ans[t.x][t.y] + ans[s.x][s.y];
 57                         return;
 58                     }
 59                     ans[t.x][t.y] = t.vis;    
 60                     visited[t.x][t.y]=2;  // 标记为在反向队列中
 61                     Q.push(t);  // 入队
 62                 }
 63             }
 64         }
 65     } 
 66 }
 67 
 68 void TBFS()
 69 {
 70     memset(visited,0,sizeof(visited));  // 判重数组
 71     while(!Q1.empty())  Q1.pop();   // 正向队列
 72     while(!Q2.empty())  Q2.pop();  // 反向队列
 73     //======正向扩展的状态标记为1,反向扩展标记为2
 74     visited[s1.x][s1.y]=1;   // 初始状态标记为1
 75     visited[s2.x][s2.y]=2;   // 结束状态标记为2
 76 
 77     s1.vis = 0;
 78     s2.vis = 1;
 79 
 80     ans[s1.x][s1.y] = 0;
 81     ans[s2.x][s2.y] = 1;
 82 
 83     Q1.push(s1);  // 初始状态入正向队列
 84     Q2.push(s2);  // 结束状态入反向队列
 85     while(!Q1.empty() || !Q2.empty())
 86     {
 87         if(!Q1.empty())
 88             BFS_expand(Q1,true);  // 在正向队列中搜索
 89         if(found)  // 搜索结束 
 90             return ;
 91         if(!Q2.empty())
 92             BFS_expand(Q2,false);  // 在反向队列中搜索
 93         if(found) // 搜索结束
 94             return ;
 95     }
 96 }
 97 
 98 
 99 int main(void)
100 {
101     int a,b,c,d,t;
102     scanf("%d",&t);
103     while(t--)
104     {
105         scanf("%d",&n);
106         m = n;
107         found = false;
108         scanf("%d %d %d %d",&a,&b,&c,&d);
109         if(a == c && b == d)
110             printf("0\n");
111         else
112         {
113             s1.x = a;
114             s1.y = b;
115             s2.x = c;
116             s2.y = d;
117             result = 0;
118             TBFS();
119             printf("%d\n",result);
120         }
121         
122     }
123     return 0;
124 }

转载于:https://www.cnblogs.com/asen32/archive/2012/08/18/2645647.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值