广度优先搜索
通过队列实现
图1.
POJ 3278
Catch That Cow
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 119172 Accepted: 37183
Description
Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.
- Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
- Teleporting: FJ can move from any point X to the point 2 × X in a single minute.
If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?
Input
Line 1: Two space-separated integers: N and K
Output
Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.
Sample Input
5 17
Sample Output
4
Hint
The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.
分析
图二。
例题给了一种方法,定义结构体,结构体中包括每个位置和到达该位置所需的步数
//poj3278 Catch That Cow
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
int N,K;
const int MAXN = 100000;
int visited[MAXN+10]; // 判重标记,visited[i] = true 表示i 已经扩展过
struct Step{
int x; // 位置
int steps; // 到达x 所需的步数
Step(int xx,int s):x(xx),steps(s) { }
};
queue<Step> q; // 队列, 即Open 表
int main() {
cin >> N >> K;
memset(visited,0,sizeof(visited));
q.push(Step(N,0));
visited[N] = 1;
23
while(!q.empty()) {
Step s = q.front();
if( s.x == K ) { // 找到目标
cout << s.steps <<endl;
return 0;
}
else {
if( s.x - 1 >= 0 && !visited[s.x-1] ) {
q.push(Step(s.x-1,s.steps+1));
visited[s.x-1] = 1;
}
if( s.x + 1 <= MAXN && !visited[s.x+1] ) {
q.push(Step(s.x+1,s.steps+1));
visited[s.x+1] = 1;
}
24
if( s.x * 2 <= MAXN &&!visited[s.x*2] ) {
q.push(Step(s.x*2,s.steps+1));
visited[s.x*2] = 1;
}
q.pop();
}
}
return 0;
}
我用了另一种方法,通过广搜来最终找到要找的位置,在寻找的过程中记录每个位置的上一个位置,最终从重点回溯直到起点,看用了多少步,在空间和时间上都会造成浪费
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<stdio.h>
using namespace std;
int main()
{
int n, k,m;
cin >> n >> k;
int book[100002] = {0};//标记是否被访问过
int B[100002];//存储用到的队列
int head[100002];// head[i]代表为i的数的上一节点的下标;如上图
int front=0,rear=0;
book[n] = 1;//先标记并入队
B[rear++] = n;
head[n] = -1;//对起点的父节点定义为-1;
while (front!=rear)
{
m = B[front++];
if (m == k)//如果找到k,
{
int step = 0;//代表走的最短步数
while (head[m] != -1)//向上找父节点,直到找到起点为止
{
m = head[m];
step++;
}
cout << step << endl;
return 0;
}
else
{
if (m - 1 >= 0 && book[m - 1] == 0)//后退一步
{
B[rear++] = m - 1;
book[m - 1] = 1;
head[m - 1] = m;//定义m-1的父节点为m
}
if (m + 1 <= 100000 && book[m + 1] == 0)//前进一步
{
B[rear++] = m + 1;
book[m + 1] = 1;
head[m + 1] = m;
}
if (2 * m <= 100000 && book[2 * m] == 0)//移动到2*m
{
B[rear++] = 2 * m;
book[m * 2] = 1;
head[2 * m] = m;
}
}
}
}