Skip to content

Commit 8458267

Browse files
author
AnfangRobkit
committed
BfS
1 parent b95498a commit 8458267

File tree

4 files changed

+186
-45
lines changed

4 files changed

+186
-45
lines changed

4.算法基础/week8/CatchCow.cpp

Lines changed: 86 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,99 @@
1-
/*
2-
//农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)
3-
农夫有两种移动方式:
4-
1、从X移动到X-1或X+1,每次移动花费一分钟
5-
2、从X移动到2*X,每次移动花费一分钟
6-
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
7-
*/
8-
#include <iostream>
9-
#include <cstring>
10-
#include <queue>
1+
#include<iostream>
2+
#include<queue>
113
using namespace std;
12-
int N, K;
13-
const int MAXN = 100000;
14-
int visited[MAXN + 10]; //判重标记,为true表示该点已经扩展过了
15-
struct Step
4+
5+
const int board_size = 4;
6+
const int direction_num = 4;
7+
struct Piece
168
{
17-
int x; //位置
18-
int steps; //到达x需要的步数
19-
Step(int xx, int ss) : x(xx), steps(ss) {}
9+
int status;//状态值
10+
int steps; //步数
11+
Piece(int st, int step):status(st),steps(step){}
2012
};
21-
queue<Step> q; //队列,即open表
22-
int main()
13+
int direction[direction_num][2] = {
14+
{-1,0}, {0,1},{1,0},{0,-1}
15+
};
16+
int pos[board_size *board_size]; //16种反转可能性
17+
bool marker[1<<(board_size*board_size)];
18+
19+
bool inBoard(int x, int y)
2320
{
24-
cin >> N >> K;
25-
memset(visited, 0, sizeof(visited));
26-
q.push(Step(N, 0)); //把起始位置放入Open表
27-
while (!q.empty())
21+
if(x>=0 && x<board_size && y>=0 && y<board_size)
22+
return true;
23+
else
24+
return false;
25+
}
26+
void FlipInitialize()
27+
{
28+
for (int i = 0; i < board_size; i++)
2829
{
29-
Step s = q.front(); //拿出Open表中第一个元素
30-
if (s.x == K)
31-
{ //找到目标
32-
cout << s.steps << endl;
33-
return 0;
34-
}
35-
else
30+
for(int j = 0; j< board_size; j++)
3631
{
37-
if (s.x - 1 >= 0 && !visited[s.x - 1])
32+
// i*size+j 即为编号
33+
int value = 1 << (i * board_size + j);
34+
for(int k = 0; k<direction_num; k++)
3835
{
39-
q.push(Step(s.x - 1, s.steps + 1));
40-
visited[s.x - 1] = 1;
36+
int next_x = i + direction[k][0];
37+
int next_y = j + direction[k][1];
38+
if(inBoard(next_x, next_y))
39+
value += 1 << (next_x *board_size + next_y);
4140
}
42-
if (s.x + 1 <= MAXN && !visited[s.x + 1])
43-
{
44-
q.push(Step(s.x + 1, s.steps + 1));
45-
visited[s.x + 1] = 1;
46-
}
47-
if (s.x * 2 <= MAXN && !visited[s.x * 2])
41+
pos[i * board_size + j] = value;
42+
}
43+
}
44+
45+
}
46+
int BFS(int value)
47+
{
48+
queue<Piece> q;
49+
Piece s = Piece(value, 0);
50+
q.push(s);
51+
marker[s.status] = true;
52+
while (!q.empty())
53+
{
54+
Piece cur = q.front();
55+
q.pop();
56+
//盘面全黑或者全白(2^16 -1)时结束,并返回步数
57+
if(cur.status == 0 || cur.status == (1<<(board_size*board_size))-1)
58+
{
59+
return cur.steps;
60+
}
61+
//搜索16个位置
62+
for(int i = 0; i< board_size*board_size; ++i)
63+
{
64+
//通过异或运算得到翻转后的状态
65+
Piece next = Piece(cur.status ^ pos[i], cur.steps+1);
66+
if(!marker[next.status])
4867
{
49-
q.push(Step(s.x * 2, s.steps + !));
50-
visited[s.x * 2] = 1;
68+
q.push(next);
69+
marker[next.status] = true;
5170
}
52-
q.pop();
71+
5372
}
5473
}
55-
return 0;
74+
return -1; //无法到达目标状态 返回-1
5675
}
76+
int main()
77+
{
78+
FlipInitialize();
79+
char str[5];
80+
int value = 0;
81+
for(int i=0; i<board_size; i++)
82+
{
83+
cin>>str;
84+
for(int j=0; j<board_size; j++)
85+
{
86+
if(str[j]== 'w')
87+
value += 1<<(i*board_size + j);
88+
// 加上 1<<(编号) 即可将此位置设置为1
89+
}
90+
}
91+
int ans = BFS(value);
92+
if(ans >= 0)
93+
cout<<ans<<endl;
94+
else
95+
{
96+
cout<<"Impossible"<<endl;
97+
}
98+
return 0;
99+
}

4.算法基础/week8/README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,23 @@ int main()
123123
DBFS算法是对BFS算法的一种扩展。
124124
125125
- BFS算法从起始节点以广度优先的顺序不断扩展,知道遇到目的节点。
126-
- DBFS算法从两个节点以广度优先的顺序同时扩展,一个是从其实节点开始扩展,一个是从目的节点开始扩展,知道一个扩展队列中出现了另一个队列中已经扩展的节点,就相当于两个扩展的方向有了交点,那么可以认为我们找到了一条路径。
126+
- DBFS算法从两个节点以广度优先的顺序同时扩展,一个是从其实节点开始扩展,一个是从目的节点开始扩展,知道一个扩展队列中出现了另一个队列中已经扩展的节点,就相当于两个扩展的方向有了交点,那么可以认为我们找到了一条路径。
127+
128+
DBFS算法相对于BFS算法来说,由于采用了双向扩展的方式,搜索树的宽度得到了明显的减少,所以在算法的时间复杂度和空间 复杂度上都有较大的优势。
129+
130+
- 假设1个结点能扩展出n个结点,单向搜索要m层能找到答案,那么扩展出来的节点数目就是: (1-$n^m$)/(1-n)
131+
- 双向广搜,同样是一共扩展m层,假定两边各扩展出m/2层,则总结点数目 2 * (1-$n^{m/2}$)/(1-n)
132+
- 每次扩展结点总是选择结点比较少的那边进行扩展,并不是机械的两边交替.
133+
134+
```cpp
135+
int expand(i) //其中i为队列的编号,0或1
136+
{
137+
取队列qi的头结点H;
138+
对H的每一个相邻节点adj:
139+
1 如果adj已经在队列qi之中出现过,则抛弃adj;
140+
2 如果adj在队列qi中未出现过,则:
141+
1) 将adj放入队列qi;
142+
2) 如果adj 曾在队列q1-i中出现过, 则:输出找到的路径
143+
}
144+
```
145+

4.算法基础/week8/assignment/flip_games.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ int main()
9393
cout<<ans<<endl;
9494
else
9595
{
96-
cout<<"Impossible"<<endl;
96+
cout<<"impossible"<<endl;
9797
}
9898
return 0;
9999
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#include <iostream>
2+
#include <queue>
3+
#include <string.h>
4+
using namespace std;
5+
6+
bool is_wall[5][5];
7+
int a[5][5];
8+
int dx[4] = {0, 1, 0, -1};
9+
int dy[4] = {1, 0, -1, 0};
10+
11+
struct Node
12+
{
13+
int x;
14+
int y;
15+
int s;
16+
short father[30];
17+
};
18+
19+
bool Judge_Invalid(int x, int y)
20+
{
21+
if(x<0 || x >=5 || y <0 || y>=5)
22+
return true;
23+
if(is_wall[x][y])
24+
return true;
25+
if(a[x][y] ==1)
26+
return true;
27+
return false;
28+
}
29+
Node Bfs()
30+
{
31+
queue<Node> q;
32+
Node cur, next;
33+
cur.x = 0;
34+
cur.y = 0;
35+
cur.s = 0;
36+
is_wall[cur.x][cur.y] = true;
37+
q.push(cur);
38+
while (!(q.empty()))
39+
{
40+
cur = q.front();
41+
q.pop();
42+
if(cur.x == 4 && cur.y ==4)
43+
return cur;
44+
int i, nx, ny;
45+
for(i=0; i<4; i++)
46+
{
47+
nx = cur.x + dx[i];
48+
ny = cur.y + dy[i];
49+
if(Judge_Invalid(nx,ny))
50+
continue;
51+
next = cur;
52+
next.x = nx;
53+
next.y = ny;
54+
next.s = cur.s + 1;
55+
next.father[cur.s] = i;
56+
q.push(next);
57+
}
58+
}
59+
return cur;
60+
}
61+
int main()
62+
{
63+
int i,j;
64+
for(i=0;i<5;i++){ //读入迷宫
65+
for(j=0;j<5;j++){
66+
scanf("%d",&a[i][j]);
67+
}
68+
}
69+
memset(is_wall,0,sizeof(is_wall));
70+
Node ans = Bfs();
71+
int x,y;
72+
x = 0,y = 0;
73+
for(i=0;i<=ans.s;i++){
74+
printf("(%d, %d)\n",x,y);
75+
x+=dx[ans.l[i]];
76+
y+=dy[ans.l[i]];
77+
}
78+
return 0;
79+
}

0 commit comments

Comments
 (0)