欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

深搜广搜专题【DFS】【BFS】

程序员文章站 2022-03-26 10:36:17
...

深搜广搜专题

又是一年专题时,这次的专题是BFS和DFS,我们刚加入acm时的噩梦,然而现在已经写起来很舒服了(OS:那你还A不出题?)

BFS和DFS都是通过对所有的点进行遍历来得到结果的,是一种比较暴力的方法,在平时较难的题目中一般不会出现。

 


A - Oil Deposits

The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid.

Input

The input contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either `*', representing the absence of oil, or `@', representing an oil pocket. 

Output

are adjacent horizontally, vertically, or diagonally. An oil deposit will not contain more than 100 pockets.

Sample Input

1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5 
****@
*@@*@
*@**@
@@@*@
@@**@
0 0

Sample Output

0
1
2
2

题意

给你一个二维平面图,*代表空,@代表下有油层,@及其相邻的@(包含斜对角)代表一个油田,问共有多少个不同的油田

思路

简单的暴力搜索,需要注意斜对角线上相邻的油也算在同一个油田中,在遍历的时候我们先搜索到一块油,对这块油进行dfs,将与其相邻的油都归属到同一个油田中,并将其重新标号为*,防止重复。

AC代码

//#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <algorithm>
#include <set>
#include <list>
#include <stack>
//#include <map>
#include <bitset>
//#define INF 0x3f3f3f3f
//#define MAX 1e9
//#define N 1000005
#define ll long long
#define G 0
#define R 1
#define P 2
#define MOD 1000000007

using namespace std;

int n, m;
char map[101][101];

void dfs(int x, int y)
{
	map[x][y] = '*';
	int xt, yt;
	int next[8][2] = { {1,0},{0,1},{0,-1},{-1,0},{1,1},{1,-1},{-1,-1},{-1,1} };
	for(int i=0;i<8;i++)
	{
		xt = x + next[i][1];
		yt = y + next[i][0];
		if (xt >= m || xt<0 || yt >= n || yt < 0)continue;
		if (map[xt][yt] == '*')continue;
		dfs(xt, yt);
	}
}

int main()
{
	while(~scanf("%d%d",&m,&n))
	{
		getchar();
		if (!m)break;
		for (int i = 0; i < m; i++)
		{
				scanf("%s", &map[i]);
		}
		int count = 0;
		for (int i = 0; i < m; i++)
		{
			for (int j = 0; j < n; j++)
			{
				if(map[i][j]=='@')
				{
					count++;
					dfs(i, j);
				}
			}
		}
		printf("%d\n", count);
	}
	//system("PAUSE");
	return 0;
}

 

 


D - Prime Ring Problem 

A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime. 

Note: the number of first circle should always be 1. 

深搜广搜专题【DFS】【BFS】 

Input

n (0 < n < 20). 

Output

The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order. 

You are to write a program that completes above process. 

Print a blank line after each case. 

Sample Input

6
8

Sample Output

Case 1:
1 4 3 2 5 6
1 6 5 2 3 4

Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2

题意

给我们一个环,从数字1开始,每两个相邻的数之和必须是一个质数,要你将可能的数按字典序升序输出。

思路

质环问题,我们对每个点进行枚举,判断该点和上一个点之间是否满足题目,若不满足则及时剪枝,避免浪费时间,需要注意的是我们当判断到最后一个点时需要将其与第一个点进行求和并求其是否是一个质数。对于本题来说最大数字之间的和不超过40,我们可以通过手动打出质数表来判断一个数是否是质数。

AC代码

//#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <algorithm>
#include <set>
#include <list>
#include <stack>
//#include <map>
#include <bitset>
#include <queue>
#define INF 0x3f3f3f3f
//#define MAX 1e9
//#define N 1000005
#define ll long long
#define G 0
#define R 1
#define P 2
#define MOD 1000000007

using namespace std;

int prime[40] = { 0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0 };
int vis[21];
int n;

vector<int>seq;

void dfs(int x)
{
	if(seq.size()==n&&prime[x+seq[0]])
	{
		for (int i = 0; i<seq.size(); ++i)
		{
			cout << seq[i];
			if (i == seq.size() - 1)cout << endl;
			else cout << " ";
		}
		return;
	}
	for(int i=2;i<=n;i++)
	{
		if(prime[x+i]&&!vis[i])
		{
			vis[i] = true;
			seq.push_back(i);
			dfs(i);
			seq.pop_back();
			vis[i] = false;
		}
	}
}

int main()
{
	//for (int i = 0; i < 40; i++)
		//if (prime[i])cout << i << " ";
	ll c = 0;
	while(~scanf("%d",&n))
	{
		cout << "Case " << ++c << ":" << endl;
		memset(vis, 0, sizeof vis);
		seq.push_back(1);
		dfs(1);
		seq.pop_back();
		cout << endl;
	}
	//system("PAUSE");
	return 0;
}




 


 

E - A计划

可怜的公主在一次次被魔王掳走一次次被骑士们救回来之后,而今,不幸的她再一次面临生命的考验。魔王已经发出消息说将在T时刻吃掉公主,因为他听信谣言说吃公主的肉也能长生不老。年迈的国王正是心急如焚,告招天下勇士来拯救公主。不过公主早已习以为常,她深信智勇的骑士LJ肯定能将她救出。 
现据密探所报,公主被关在一个两层的迷宫里,迷宫的入口是S(0,0,0),公主的位置用P表示,时空传输机用#表示,墙用*表示,平地用.表示。骑士们一进入时空传输机就会被转到另一层的相对位置,但如果被转到的位置是墙的话,那骑士们就会被撞死。骑士们在一层中只能前后左右移动,每移动一格花1时刻。层间的移动只能通过时空传输机,且不需要任何时间。

Input

输入的第一行C表示共有C个测试数据,每个测试数据的前一行有三个整数N,M,T。 N,M迷宫的大小N*M(1 <= N,M <=10)。T如上所意。接下去的前N*M表示迷宫的第一层的布置情况,后N*M表示迷宫第二层的布置情况。

Output

如果骑士们能够在T时刻能找到公主就输出“YES”,否则输出“NO”。

Sample Input

1
5 5 14
S*#*.
.#...
.....
****.
...#.

..*.P
#.*..
***..
...*.
*.#..

Sample Output

YES

题意

这次是一个广搜问题,我们每一层的搜索对应一个时刻,在这个时刻内假设有足够多的骑士移动至所有能到达的格子,循环往复,若找到公主,则检查该点所对应的时刻是否满足题意,若不满足则输出NO,还有一种情况就是公主根本不可达,我们在队列内部所有点都无法继续拓展直到队列为空后输出NO。对于传送门,当时没有想到可能会有一个传送门可以直接传送到另一个传送门的情况(掉入传送门的嵌套中无法脱身什么的,有点惊悚)WA了。

AC代码

//#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <algorithm>
#include <set>
#include <list>
#include <stack>
//#include <map>
#include <bitset>
#include <queue>
#define INF 0x3f3f3f3f
//#define MAX 1e9
//#define N 1000005
#define ll long long
#define G 0
#define R 1
#define P 2
#define MOD 1000000007

using namespace std;

int prime[40] = { 0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0 };
int vis[21];
int n;

vector<int>seq;

void dfs(int x)
{
	if(seq.size()==n&&prime[x+seq[0]])
	{
		for (int i = 0; i<seq.size(); ++i)
		{
			cout << seq[i];
			if (i == seq.size() - 1)cout << endl;
			else cout << " ";
		}
		return;
	}
	for(int i=2;i<=n;i++)
	{
		if(prime[x+i]&&!vis[i])
		{
			vis[i] = true;
			seq.push_back(i);
			dfs(i);
			seq.pop_back();
			vis[i] = false;
		}
	}
}

int main()
{
	//for (int i = 0; i < 40; i++)
		//if (prime[i])cout << i << " ";
	ll c = 0;
	while(~scanf("%d",&n))
	{
		cout << "Case " << ++c << ":" << endl;
		memset(vis, 0, sizeof vis);
		seq.push_back(1);
		dfs(1);
		seq.pop_back();
		cout << endl;
	}
	//system("PAUSE");
	return 0;
}




 


F - 胜利大逃亡

 

Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会. 

魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,现在知道魔王将在T分钟后回到城堡,Ignatius每分钟能从一个坐标走到相邻的六个坐标中的其中一个.现在给你城堡的地图,请你计算出Ignatius能否在魔王回来前离开城堡(只要走到出口就算离开城堡,如果走到出口的时候魔王刚好回来也算逃亡成功),如果可以请输出需要多少分钟才能离开,如果不能则输出-1. 

深搜广搜专题【DFS】【BFS】

 

Input

输入数据的第一行是一个正整数K,表明测试数据的数量.每组测试数据的第一行是四个正整数A,B,C和T(1<=A,B,C<=50,1<=T<=1000),它们分别代表城堡的大小和魔王回来的时间.然后是A块输入数据(先是第0块,然后是第1块,第2块......),每块输入数据有B行,每行有C个正整数,代表迷宫的布局,其中0代表路,1代表墙.(如果对输入描述不清楚,可以参考Sample Input中的迷宫描述,它表示的就是上图中的迷宫) 

特别注意:本题的测试数据非常大,请使用scanf输入,我不能保证使用cin能不超时.在本OJ上请使用Visual C++提交. 

Output

对于每组测试数据,如果Ignatius能够在魔王回来前离开城堡,那么请输出他最少需要多少分钟,否则输出-1. 

Sample Input

1
3 3 4 20
0 1 1 1
0 0 1 1
0 1 1 1
1 1 1 1
1 0 0 1
0 1 1 1
0 0 0 0
0 1 1 0
0 1 1 0

Sample Output

11

题意

不就是上一题迷宫从两层变成多层嘛效果一样的呀 (暴言)

我们将上题的迷宫层数以及终点的判断稍加修改,就可以AC本题啦!

其实并不能,那样会TLE......我们可以看出,在某些情况下我们的主人公是无论如何都无法逃出升天的,一种情况是出口就是一堵墙,我们无法穿过出口,第二种情况是主人公距离出口太远,以至于毫无阻碍的情况下走向出口都无法离开,我们将这两种情况加入代码后,就真的AC了。

AC代码

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <algorithm>
#include <set>
#include <list>
#include <stack>
//#include <map>
#include <bitset>
#include <queue>
#include <ctime>
#define INF 0x3f3f3f3f
//#define MAX 1e9
#define N 105
//#define ll long long
//#define MOD 1000000007

using namespace std;

int a, b, c, t;
int casle[51][51][51];

struct pos
{
	int x;
	int y;
	int z;
	int step;
};

queue<pos>que;

int bfs()
{
	//缺少前两个特判会使程序TLE
	if (casle[a - 1][b - 1][c - 1])return -1;
	if (a + b + c - 3 > t)return -1;
	int book[51][51][51] = { 0 };
	book[0][0][0] = true;
	que.push({ 0,0,0 });
	while(!que.empty())
	{
		if (que.front().z == a - 1 && que.front().x == c - 1 && que.front().y == b - 1)
		{
			if (que.front().step <= t) return que.front().step;
		}
		int next[6][3] = { {1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1} };
		for (int i = 0; i < 6; i++)
		{
			int tx = que.front().x + next[i][0];
			int ty = que.front().y + next[i][1];
			int tz = que.front().z + next[i][2];
			if (tx < 0 || ty < 0 || tz < 0 || tx >= c || ty >= b || tz >= a)continue;
			if (!book[tz][ty][tx] && casle[tz][ty][tx] != 1 && que.front().step + 1 <= t)
			{
				book[tz][ty][tx] = true;
				que.push({ tx,ty,tz,que.front().step + 1 });
			}
		}
		que.pop();
	}
	return -1;
}

int main()
{
	int C;
	scanf("%d", &C);
	while(C--)
	{
		scanf("%d%d%d%d", &a, &b, &c, &t);
		//注意清空
		while (!que.empty())que.pop();
		getchar();
		for (int lev = 0; lev < a; lev++)
		{
			for (int i = 0; i < b; i++)
			{
				for (int j = 0; j < c; j++)
					scanf("%d", &casle[lev][i][j]);
			}
		}
		printf("%d\n", bfs());
	}
	//system("PAUSE");
	return 0;
}

 


 G - Asteroids!

You're in space. 
You want to get home. 
There are asteroids. 
You don't want to hit them. 

Input

Input to this problem will consist of a (non-empty) series of up to 100 data sets. Each data set will be formatted according to the following description, and there will be no blank lines separating data sets. 

A single data set has 5 components: 

Start line - A single line, "START N", where 1 <= N <= 10. 

Slice list - A series of N slices. Each slice is an N x N matrix representing a horizontal slice through the asteroid field. Each position in the matrix will be one of two values: 

'O' - (the letter "oh") Empty space 

'X' - (upper-case) Asteroid present 

Starting Position - A single line, "A B C", denoting the <A,B,C> coordinates of your craft's starting position. The coordinate values will be integers separated by individual spaces. 

Target Position - A single line, "D E F", denoting the <D,E,F> coordinates of your target's position. The coordinate values will be integers separated by individual spaces. 

End line - A single line, "END" 

The origin of the coordinate system is <0,0,0>. Therefore, each component of each coordinate vector will be an integer between 0 and N-1, inclusive. 

The first coordinate in a set indicates the column. Left column = 0. 

The second coordinate in a set indicates the row. Top row = 0. 

The third coordinate in a set indicates the slice. First slice = 0. 

Both the Starting Position and the Target Position will be in empty space. 
 

Output

For each data set, there will be exactly one output set, and there will be no blank lines separating output sets. 

A single output set consists of a single line. If a route exists, the line will be in the format "X Y", where X is the same as N from the corresponding input data set and Y is the least number of moves necessary to get your ship from the starting position to the target position. If there is no route from the starting position to the target position, the line will be "NO ROUTE" instead. 

A move can only be in one of the six basic directions: up, down, left, right, forward, back. Phrased more precisely, a move will either increment or decrement a single component of your current position vector by 1. 
 

Sample Input

START 1
O
0 0 0
0 0 0
END
START 3
XXX
XXX
XXX
OOO
OOO
OOO
XXX
XXX
XXX
0 0 1
2 2 1
END
START 5
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
XXXXX
XXXXX
XXXXX
XXXXX
XXXXX
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
OOOOO
0 0 0
4 4 4
END

Sample Output

1 0
3 4
NO ROUTE

题意

太空中有一大片小行星带,你需要穿过它们,输入空间中小行星分布情况,问你是否可以穿过,若可以穿过输出最短步数。

思路

这题完全,完全完全没有什么需要注意的地方......我要是说再把上面的AC代码拿下来改改输入的话应该不会被打死吧?不会吗?太好了那就这么办吧!

AC代码

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <algorithm>
#include <set>
#include <list>
#include <stack>
//#include <map>
#include <bitset>
#include <queue>
#include <ctime>
#define INF 0x3f3f3f3f
//#define MAX 1e9
#define N 105
//#define ll long long
//#define MOD 1000000007

using namespace std;

int a, b, n;
int sx, sy, sz, ex, ey, ez;

char space[11][11][11];

struct pos
{
	int x;
	int y;
	int z;
	int times;
};

queue<pos>que;

int bfs()
{
	int book[11][11][11] = { 0 };
	book[sz][sy][sx] = true;
	que.push({ sx,sy,sz,0 });
	while(!que.empty())
	{
		if (que.front().x == ex && que.front().y == ey && que.front().z == ez)
		{
			return que.front().times;
		}
		int next[6][3] = { { 1,0,0 },{ 0,1,0 },{ 0,0,1 },{ -1,0,0 },{ 0,-1,0 },{ 0,0,-1 } };
		for(int i=0;i<6;i++)
		{
			int tx = que.front().x + next[i][0];
			int ty = que.front().y + next[i][1];
			int tz = que.front().z + next[i][2];
			if (tx < 0 || ty < 0 || tz < 0 || tx >= n || ty >= n || tz >= n)continue;
			if(space[tz][ty][tx]!='X'&&!book[tz][ty][tx])
			{
				book[tz][ty][tx] = true;
				que.push({ tx,ty,tz,que.front().times + 1 });
			}
		}
		que.pop();
	}
	return -1;
}

int main()
{
	char c[10];
	while (~scanf("%s", c))
	{
		scanf("%d", &n);
		getchar();
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				scanf("%s", &space[i][j]);
			}
		}
		scanf("%d%d%d", &sx, &sy, &sz);
		scanf("%d%d%d", &ex, &ey, &ez);
		getchar();
		scanf("%s", c);
		//注意清空
		while (!que.empty())que.pop();
		int temp = bfs();
		if (temp != -1)
			printf("%d %d\n", n, temp);
		else printf("NO ROUTE\n");
	}
	//system("PAUSE");
	return 0;
}

 


H - A strange lift

There is a strange lift.The lift can stop can at every floor as you want, and there is a number Ki(0 <= Ki <= N) on every floor.The lift have just two buttons: up and down.When you at floor i,if you press the button "UP" , you will go up Ki floor,i.e,you will go to the i+Ki th floor,as the same, if you press the button "DOWN" , you will go down Ki floor,i.e,you will go to the i-Ki th floor. Of course, the lift can't go up high than N,and can't go down lower than 1. For example, there is a buliding with 5 floors, and k1 = 3, k2 = 3,k3 = 1,k4 = 2, k5 = 5.Begining from the 1 st floor,you can press the button "UP", and you'll go up to the 4 th floor,and if you press the button "DOWN", the lift can't do it, because it can't go down to the -2 th floor,as you know ,the -2 th floor isn't exist. 
Here comes the problem: when you are on floor A,and you want to go to floor B,how many times at least he has to press the button "UP" or "DOWN"? 

Input

The input consists of several test cases.,Each test case contains two lines. 
The first line contains three integers N ,A,B( 1 <= N,A,B <= 200) which describe above,The second line consist N integers k1,k2,....kn. 
A single 0 indicate the end of the input.

Output

For each case of the input output a interger, the least times you have to press the button when you on floor A,and you want to go to floor B.If you can't reach floor B,printf "-1".

Sample Input

5 1 5
3 3 1 2 5
0

Sample Output

3

题意

一部迷之电梯,在每一层开始移动时只按照该层的指定移动层数上下移动, 问有没有可能从某一楼到另外一楼。

思路

这题不再是遍历图的问题了,而是有规律的线性移动,我们将dfs的移动方式稍加修改,将每一层的移动位置定为该层输入的指定移动层数,使其移动规律符合题意便可。需要注意的是电梯仅能在输入的层中间移动,要是捅穿屋顶了或者扎进地下的话不算。

AC代码

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <algorithm>
#include <set>
#include <list>
#include <stack>
//#include <map>
#include <bitset>
#include <queue>
#include <ctime>
#define INF 0x3f3f3f3f
//#define MAX 1e9
#define N 105
//#define ll long long
//#define MOD 1000000007

using namespace std;

int a, b, n;

struct pos
{
	int floor;
	int times;
};

queue<pos>que;

int moves[205];

int bfs()
{
	int book[205] = { 0 };
	book[a] = true;
	que.push({ a,0 });
	while(!que.empty())
	{
		int temp = que.front().floor;
		if (temp == b)return que.front().times;
		if (temp - moves[temp] > 0)
		{
			if (!book[temp - moves[temp]])
			{
				book[temp - moves[temp]] = true;
				que.push({ temp - moves[temp],que.front().times + 1 });
			}
		}
		if (temp + moves[temp] <= n)
		{
			if(!book[temp + moves[temp]])
			{
				book[temp + moves[temp]] = true;
				que.push({ temp + moves[temp] ,que.front().times + 1 });
			}
		}
		que.pop();
	}
	return -1;
}

int main()
{
	while (~scanf("%d", &n))
	{
		if (!n)break;
		scanf("%d%d", &a, &b);
		//注意清空
		while (!que.empty())que.pop();
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &moves[i]);
		}
		printf("%d\n", bfs());
	}
	//system("PAUSE");
	return 0;
}

 

 


I - Catch That Cow

 

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.

题意

在一条直线上,一个带了闪现的农夫要抓牛,这个农夫有三种移动方式分别为向前向后一步,在当前的点坐标上闪现到两倍当前坐标的位置,问最短移动多少次能抓到。

思路

又到了愉快的修改前一道题代码的时间啦!

我们将上题的移动方式改为本题移动方式,并且将上题中的移动范围限制去除即可。需要注意的是我们在当前位置不比牛大时有三种移动方式,前后移动和向前闪现,在当前位置比牛大后便仅有向后移动是有意义的,此处可以剪枝,除去无意义的判断。什么,你问我要是不剪会怎么样?我咋知道,万一TLE了呢?

AC代码

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <string>
#include <list>
#include <algorithm>
#include <set>
#include <list>
#include <stack>
//#include <map>
#include <bitset>
#include <queue>
#include <ctime>
#define INF 0x3f3f3f3f
//#define MAX 1e9
#define N 105
//#define ll long long
//#define MOD 1000000007

using namespace std;

int n, k;

struct pos
{
	int x;
	int min;
};

queue<pos>que;

int move(int x,int times)
{
		switch(times)
		{
		case 2:return x * 2;
		case 1:return x + 1;
		case 0:return x - 1;
		}
}

int bfs()
{
	int book[200000] = { 0 };
	book[n] = true;
	que.push({ n, 0 });
	while(!que.empty())
	{
		if (que.front().x == k )
		{
			return que.front().min;
		}
		int tx = que.front().x;
		int t;
		if (tx < k)t = 3;
		else t = 1;
		while (t--)
		{
			int x = move(tx, t);
			if(!book[x])
			{
				book[x] = true;
				que.push({ x,que.front().min + 1 });
			}
		}
		que.pop();
	}
}

int main()
{
	while (~scanf("%d%d", &n, &k))
	{
		//注意清空
		while (!que.empty())que.pop();
		printf("%d\n", bfs());
	}
	//system("PAUSE");
	return 0;
}

 


本次题解中还有B题和C题没有AC出来,B题迷之坑,花了我一天的时间测试各种能想到以及找到的样例都无法定位BUG,如果我能AC就补题解吧!嗯!

深搜广搜专题【DFS】【BFS】