广度优先搜索--抓住那头牛(poj 3278)
2017-11-26 10:52
337 查看
描述
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:
1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
输入两个整数,N和K
输出一个整数,农夫抓到牛所要花费的最小分钟数
样例输入
样例输出
广度优先搜索算法如下:(用QUEUE)
(1)
把初始节点S0放入Open表中;
(2)
如果Open表为空,则问题无解,失败退出;
(3)
把Open表的第一个节点取出放入Closed表,并记该节点为n;
(4)
考察节点n是否为目标节点。若是,则得到问题的解,成功退出;
(5)
若节点n不可扩展,则转第(2)步;
(6)
扩展节点n,将其不在Closed表和Open表中的子节点(判重)放入Open表的尾部,并为每一个子节点设置指向父节点的指针(或记录节点的层次),然后转第(2)步。
先看一个广搜遍历:
#include <iostream>
#include <queue>
#define NUM 100
using namespace std;
//广度优先搜索算法如下:(用QUEUE)
//(1) 把初始节点S0放入Open表中;
//(2) 如果Open表为空,则问题无解,失败 退出;
//(3) 把Open表的第一个节点取出放入 Closed表,并记该节点为n;
//(4) 考察节点n是否为目标节点。若是, 则得到问题的解,成功退出;
//(5) 若节点n不可扩展,则转第(2)步;
//(6) 扩展节点n,将其不在Closed表和 Open表中的子节点(判重)放入Open表的尾部 ,
//并为每一个子节点设置指向父节点的指针( 或记录节点的层次),然后转第(2)步。
int Graph[NUM][NUM];
int N,M;//顶点数和边数;
bool visit[NUM] = {false};//标记已经访问过的顶点;
void BFS(int k)
{
visit[k] = true;
queue<int> q;
//把初始节点S0放入Open表中;
q.push(k);
// 如果队列表为空,则问题无解,失败 退出;
while(!q.empty()){
// 把Open表的第一个节点取出;
int temp = q.front();
printf("%c ",temp+'a'-1);
q.pop();
for(int i = 1;i<=N;i++){
if(Graph[temp][i]==1&&!visit[i]){
visit[i] = true;
q.push(i);
}
}
}
}
int main()
{
cin>>N>>M;
for(int i =1;i<=M;i++){
char a,b;
cin>>a>>b;
int x = a-'a'+1;
int y = b-'a'+1;
Graph[x][y] = Graph[y][x] = 1;
}
//针对非连通图
for(int i = 1;i<=N;i++)
if(!visit[i])
BFS(i);
cout <<endl;
return 0;
}
//8 14
//a b
//a c
//a e
//a f
//a g
//a h
//b d
//b e
//b h
//c g
//c h
//d h
//e f
//f g
//这道题注意:
//1.这种图是无法用数据结构来存储的,这是一种未知的图;不过他的顶点个数可以得到;并且是每两个顶点之间的位置直接就可以知道的,
//这是由关系来却定的,所以在入队列的时候直接就是将其找到其邻接顶点,直接就入队了,这种能直接找到邻接顶点的直接就是开始广搜
//,不需要储蓄,因为存储的目的也就是为了将每一邻接的顶点找到,如果能直接省略的储存就直接省略了,
//2,在使用广搜的时候可能要求解其中的步数,这个时候可以将入队列的类型是一个结构体,这样在入队列的时候直接就可以将其+1,就可以将
//步数计算的到;
这道题的代码:
#include <iostream>
#include <queue>
#define NUM 100000
using namespace std;
int N,K;
bool visted[NUM+10];
struct Step{
int i;
int step;
Step(int x,int s):i(x),step(s){};//默认构造函数;
};
void BFS()//过程和层序遍历二叉数一样的;不一样就是二叉树只有两个邻接顶点,这是确定的;
{
queue<Step> q;
q.push(Step(N,0));//农夫最初的位置;
visted
= true;
while(!q.empty()){
Step s = q.front();//获取第一个顶点的值
q.pop();
if(s.i == K){
cout<<s.step<<endl;
return ;
}
else{//第一个顶点的邻接顶点入队;等待按照一层一层的输出;
if( s.i - 1 >= 0 && !visted[s.i-1] ) {
q.push(Step(s.i-1,s.step+1));
visted[s.i-1] = true;
}
if( s.i + 1 <= NUM && !visted[s.i+1] ) {
q.push(Step(s.i+1,s.step+1));
visted[s.i+1] = true;
}
if(s.i*2<=NUM&&!visted[s.i*2]){
q.push(Step(s.i*2,s.step+1));
visted[s.i*2] = true;
}
}
}
}
int main()
{
cin>>N>>K;
BFS();
return 0;
}
ps:我的很多题是用STL来解题的,如果不只到C++STL可以先去了解怎么用,相信你会喜欢他,因为很多题目一位有了他变得更简单;
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:
1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
输入两个整数,N和K
输出一个整数,农夫抓到牛所要花费的最小分钟数
样例输入
5 17
样例输出
4
广度优先搜索算法如下:(用QUEUE)
(1)
把初始节点S0放入Open表中;
(2)
如果Open表为空,则问题无解,失败退出;
(3)
把Open表的第一个节点取出放入Closed表,并记该节点为n;
(4)
考察节点n是否为目标节点。若是,则得到问题的解,成功退出;
(5)
若节点n不可扩展,则转第(2)步;
(6)
扩展节点n,将其不在Closed表和Open表中的子节点(判重)放入Open表的尾部,并为每一个子节点设置指向父节点的指针(或记录节点的层次),然后转第(2)步。
先看一个广搜遍历:
#include <iostream>
#include <queue>
#define NUM 100
using namespace std;
//广度优先搜索算法如下:(用QUEUE)
//(1) 把初始节点S0放入Open表中;
//(2) 如果Open表为空,则问题无解,失败 退出;
//(3) 把Open表的第一个节点取出放入 Closed表,并记该节点为n;
//(4) 考察节点n是否为目标节点。若是, 则得到问题的解,成功退出;
//(5) 若节点n不可扩展,则转第(2)步;
//(6) 扩展节点n,将其不在Closed表和 Open表中的子节点(判重)放入Open表的尾部 ,
//并为每一个子节点设置指向父节点的指针( 或记录节点的层次),然后转第(2)步。
int Graph[NUM][NUM];
int N,M;//顶点数和边数;
bool visit[NUM] = {false};//标记已经访问过的顶点;
void BFS(int k)
{
visit[k] = true;
queue<int> q;
//把初始节点S0放入Open表中;
q.push(k);
// 如果队列表为空,则问题无解,失败 退出;
while(!q.empty()){
// 把Open表的第一个节点取出;
int temp = q.front();
printf("%c ",temp+'a'-1);
q.pop();
for(int i = 1;i<=N;i++){
if(Graph[temp][i]==1&&!visit[i]){
visit[i] = true;
q.push(i);
}
}
}
}
int main()
{
cin>>N>>M;
for(int i =1;i<=M;i++){
char a,b;
cin>>a>>b;
int x = a-'a'+1;
int y = b-'a'+1;
Graph[x][y] = Graph[y][x] = 1;
}
//针对非连通图
for(int i = 1;i<=N;i++)
if(!visit[i])
BFS(i);
cout <<endl;
return 0;
}
//8 14
//a b
//a c
//a e
//a f
//a g
//a h
//b d
//b e
//b h
//c g
//c h
//d h
//e f
//f g
//这道题注意:
//1.这种图是无法用数据结构来存储的,这是一种未知的图;不过他的顶点个数可以得到;并且是每两个顶点之间的位置直接就可以知道的,
//这是由关系来却定的,所以在入队列的时候直接就是将其找到其邻接顶点,直接就入队了,这种能直接找到邻接顶点的直接就是开始广搜
//,不需要储蓄,因为存储的目的也就是为了将每一邻接的顶点找到,如果能直接省略的储存就直接省略了,
//2,在使用广搜的时候可能要求解其中的步数,这个时候可以将入队列的类型是一个结构体,这样在入队列的时候直接就可以将其+1,就可以将
//步数计算的到;
这道题的代码:
#include <iostream>
#include <queue>
#define NUM 100000
using namespace std;
int N,K;
bool visted[NUM+10];
struct Step{
int i;
int step;
Step(int x,int s):i(x),step(s){};//默认构造函数;
};
void BFS()//过程和层序遍历二叉数一样的;不一样就是二叉树只有两个邻接顶点,这是确定的;
{
queue<Step> q;
q.push(Step(N,0));//农夫最初的位置;
visted
= true;
while(!q.empty()){
Step s = q.front();//获取第一个顶点的值
q.pop();
if(s.i == K){
cout<<s.step<<endl;
return ;
}
else{//第一个顶点的邻接顶点入队;等待按照一层一层的输出;
if( s.i - 1 >= 0 && !visted[s.i-1] ) {
q.push(Step(s.i-1,s.step+1));
visted[s.i-1] = true;
}
if( s.i + 1 <= NUM && !visted[s.i+1] ) {
q.push(Step(s.i+1,s.step+1));
visted[s.i+1] = true;
}
if(s.i*2<=NUM&&!visted[s.i*2]){
q.push(Step(s.i*2,s.step+1));
visted[s.i*2] = true;
}
}
}
}
int main()
{
cin>>N>>K;
BFS();
return 0;
}
ps:我的很多题是用STL来解题的,如果不只到C++STL可以先去了解怎么用,相信你会喜欢他,因为很多题目一位有了他变得更简单;
相关文章推荐
- POJ 3278 Catch that cow 广度优先搜索bfs
- 广度优先搜索 入门:抓住那头牛
- POJ 3278-Catch That Cow 广度优先搜索BFS
- 广度优先搜索-抓住那头牛(算法基础 第8周)
- 广度优先搜索bfs与抓住那头奶牛(Catch that cow, poj3278)
- POJ 3278:Catch That Cow 抓住那头牛
- POJ 3126-Prime Path-广度优先搜索bfs
- 广度优先搜索--POJ迷宫问题
- poj 3278 bfs(抓住那头牛)
- poj 3278 catch that cow (广度优先BFS)
- POJ 3278 广度搜索 一个终点
- 【BFS】(一)抓住那头牛(poj 3278)
- OpenJudge noi 2971抓住那头牛(POJ 3278)
- 广度搜索(BFS)入门题目:抓住那头牛
- poj 3984 迷宫问题 BFS 图的广度优先搜索
- Prime Path - POJ 3126 BFS宽度(广度)优先搜索
- 寒假前刷题(6)广度优先搜索 poj 3126
- 广度优先搜索BFS
- Java编程实现基于图的深度优先搜索和广度优先搜索完整代码
- POJ3414 - Pots - 广度优先搜索