广度优先搜索例题

广度优先搜索(BFS)是一种基本的暴力技术,常用于解决图、树的遍历问题。

类似于一个“扩散”的过程,如果把搜索空间看成一个池塘,丢一颗石头到起点位置,激起的波浪就会一层层扩散到整个空间。需要注意的是,扩散按从近到远的顺序进行,因此,从每个被扩散到的点到起点的路径都是最短的。这个特征对解决迷宫最短路径问题很有用。

t1 poj 3278 Catch That Cow

题目大意:

农夫要去抓一只知道固定位置的牛,农夫有两种走法:1.行走:农夫可以在一分钟内从X点移动到X - 1 或X + 1点   2. 跳跃:农夫可以在一分钟内从X点移动到 2 × X点。要求的就是抓住牛的最短时间

输入:是农夫和母牛的位置,输出:所花的最短时间

ac代码如下:

#include <iostream>
#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) {}
	/*等价于
	Step(int xx, int s) {
		xx = x		;
		steps = s;
	}
	*/
};
queue<Step>q;//队列,即Open表	
int main()
{
	cin >> N >> K;
	memset(visited, 0, sizeof(visited));//所有点初始化为零
	q.push(Step(N, 0));
	visited[N] = 1;
	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;
			}
			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;
}

t2 poj 1426 Find The Multiple

题目大意:

给出一个整数n,(1 <= n <= 200)。求出任意一个它的倍数m,要求m必须只由十进制的'0'或'1'组成。

思路:

题目意思很简单,但要是采用暴力法的话是会超时的,因此,可以用一种思路简单的方法,“打表法”,也就是我们先用bfs把1到200由十进制的'0'或'1'组成的倍数m都算出来,存入到一个txt文件里。然后再直接调用即可。

代码如下:

#include <queue>
#include <iostream>
using namespace std;
typedef long long ll;
int n;
queue<ll>q;	
void bfs()
{
	while (!q.empty())
	{
		ll ans = q.front();
		q.pop();
		if (ans % n == 0)
		{
			cout << ans << "," << endl;
			return;//表示什么也不返回,仅仅用来结束函数
		}	
		q.push(ans * 10);
		q.push(ans * 10 + 1);
	}
}
int main()
{
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
	for (int i= 1; i < 201; i++)
	{
		n = i;
		while (!q.empty()) q.pop();
		q.push(1);
		bfs();
	}
	return 0;
}

打表:

#include <iostream>
using namespace std;
typedef long long ll;
int n;
ll ans[200] = {
1,
10,
111,
100,
10,
1110,
1001,
1000,
111111111,
10,
11,
11100,
1001,
10010,
1110,
10000,
11101,
1111111110,
11001,
100,
10101,
110,
110101,
111000,
100,
10010,
1101111111,
100100,
1101101,
1110,
111011,
100000,
111111,
111010,
10010,
11111111100,
111,
110010,
10101,
1000,
11111,
101010,
1101101,
1100,
1111111110,
1101010,
10011,
1110000,
1100001,
100,
100011,
100100,
100011,
11011111110,
110,
1001000,
11001,
11011010,
11011111,
11100,
100101,
1110110,
1111011111,
1000000,
10010,
1111110,
1101011,
1110100,
10000101,
10010,
10011,
111111111000,
10001,
1110,
11100,
1100100,
1001,
101010,
10010011,
10000,
1111111101,
111110,
101011,
1010100,
111010,
11011010,
11010111,
11000,
11010101,
1111111110,
1001,
11010100,
10000011,
100110,
110010,
11100000,
11100001,
11000010,
111111111111111111,
100,
101,
1000110,
11100001,
1001000,
101010,
1000110,
100010011,
110111111100,
1001010111,
110,
111,
10010000,
1011011,
110010,
1101010,
110110100,
10101111111,
110111110,
100111011,
111000,
11011,
1001010,
10001100111,
11101100,
1000,
11110111110,
11010011,
10000000,
100100001,
10010,
101001,
11111100,
11101111,
11010110,
11011111110,
11101000,
10001,
100001010,
110110101,
100100,
10011,
100110,
1001,
1111111110000,
11011010,
100010,
1100001,
11100,
110111,
11100,
1110001,
11001000,
10111110111,
10010,
1110110,
1010100,
10101101011,
100100110,
100011,
100000,
11101111,
11111111010,
1010111,
1111100,
1111110,
1010110,
11111011,
10101000,
10111101,
111010,
1111011111,
110110100,
1011001101,
110101110,
100100,
110000,
100101111,
110101010,
11010111,
11111111100,
1001111,
10010,
100101,
110101000,
1110,
100000110,
1001011,
1001100,
1010111010111,
110010,
11101111,
111000000,
11001,
111000010,
101010,
110000100,
1101000101,
1111111111111111110,
111000011,
1000,
};

int main()
{
	while (cin >> n, n)
		cout << ans[n - 1] << endl;
	return 0;
}

t3. poj 3414Pots:

题目大意:

你有两个罐子,分别有AB升的体积。可以执行以下操作:

  1. FILL(i)从水龙头填充锅i (1 ≤ i ≤ 2);
  2. DROP(i) 将锅i排空至排水管;
  3. POUR(i,j) 从锅i倒入锅j;在此操作之后,要么锅j已满(锅i 中可能还有一些水),要么锅i是空的(并且其所有内容都已移到锅j 中)。

编写一个程序,找出这些操作的最短可能序列,以便在其中一个锅中产生恰好C升的水。

输入

第一行也是唯一一行是数字ABC。这些都是 1 到 100 范围内的整数,并且C ≤max( A , B )。

输出

输出的第一行必须包含操作序列K的长度。以下K行必须每行描述一个操作。如果有几个最小长度的序列,输出其中的任何一个。如果无法达到预期的结果,文件的第一行也是唯一的一行必须包含单词“impossible”。

样本输入

3 5 4

样本输出

6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)

代码如下:

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int MAXN = 100;
int a, b, c;
bool notvist[MAXN + 1][MAXN + 1];//标记
struct node {
    int a, b, level;
    int path[MAXN + 1];//记录执行的操作
    int plen;//记录执行操作的次数
};
string path[] = {//用来表示执行的是什么操作
     "FILL(1)"
    ,"FILL(2)"
    ,"DROP(1)"
    ,"DROP(2)"
    ,"POUR(1,2)"
    ,"POUR(2,1)"
};

void output_result(int lvl, int p[], int n)//输出函数
{
    cout << lvl << endl;
    for (int i = 0; i < n; i++)
        cout << path[p[i]] << endl;
}

void bfs()
{
    queue<node> q;
    memset(notvist, true, sizeof(notvist));
    node f;
    f.a = 0;
    f.b = 0;
    f.level = 0;
    memset(f.path, 0, sizeof(f.path));
    f.plen = 0;
    q.push(f);
    notvist[f.a][f.b] = false;
    while (!q.empty()) {
        f = q.front();
        q.pop();
        if (f.a == c || f.b == c) {
            output_result(f.level, f.path, f.plen);
            return;
        }
        node v;
        v = f;
        v.level++;
        v.plen++;
        // FILL(a)
        if (a - f.a > 0) {
            v.a = a;
            v.b = f.b;
            if (notvist[v.a][v.b]) {
                v.path[f.plen] = 0;
                q.push(v);
                notvist[v.a][v.b] = false;
            }
        }
        // FILL(b)
        if (b - f.b > 0) {
            v.a = f.a;
            v.b = b;
            if (notvist[v.a][v.b]) {
                v.path[f.plen] = 1;
                q.push(v);
                notvist[v.a][v.b] = false;
            }
        }
        // DROP(a)
        if (f.a) {
            v.a = 0;
            v.b = f.b;
            if (notvist[v.a][v.b]) {
                v.path[f.plen] = 2;
                q.push(v);
                notvist[v.a][v.b] = false;
            }
        }
        // DROP(b)
        if (f.b) {
            v.a = f.a;
            v.b = 0;
            if (notvist[v.a][v.b]) {
                v.path[f.plen] = 3;
                q.push(v);
                notvist[v.a][v.b] = false;
            }
        }
        // POUR(a,b)
        if (f.a && (f.b < b)) {
            if (f.a > (b - f.b)) {
                v.a = f.a - (b - f.b);
                v.b = b;
            }
            else {
                v.a = 0;
                v.b = f.b + f.a;
            }
            if (notvist[v.a][v.b]) {
                v.path[f.plen] = 4;
                q.push(v);
                notvist[v.a][v.b] = false;
            }
        }
        // POUR(b,a)
        if (f.b && (f.a < a)) {
            if (f.b > (a - f.a)) {
                v.a = a;
                v.b = f.b - (a - f.a);
            }
            else {
                v.a = f.a + f.b;
                v.b = 0;
            }
            if (notvist[v.a][v.b]) {
                v.path[f.plen] = 5;
                q.push(v);
                notvist[v.a][v.b] = false;
            }
        }
    }
    cout << "impossible" << endl;
}

int main()
{
    cin >> a >> b >> c;
    bfs();
    return 0;
}

大数据201 liyang

猜你喜欢

转载自blog.csdn.net/zjsru_Beginner/article/details/121189529