广度优先搜索(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:
题目大意:
你有两个罐子,分别有A和B升的体积。可以执行以下操作:
- FILL(i)从水龙头填充锅i (1 ≤ i ≤ 2);
- DROP(i) 将锅i排空至排水管;
- POUR(i,j) 从锅i倒入锅j;在此操作之后,要么锅j已满(锅i 中可能还有一些水),要么锅i是空的(并且其所有内容都已移到锅j 中)。
编写一个程序,找出这些操作的最短可能序列,以便在其中一个锅中产生恰好C升的水。
输入
第一行也是唯一一行是数字A、B和C。这些都是 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