其他分享
首页 > 其他分享> > Aizu0558 -- Chesse

Aizu0558 -- Chesse

作者:互联网

题意:

在H * W的地图上有N个奶酪工厂,每个工厂分别生产硬度为1-N的奶酪。有一只老鼠准备从出发点吃遍每一个工厂的奶酪。老鼠有一个体力值,初始时为1,每吃一个工厂的奶酪体力值增加1(每个工厂只能吃一次),且老鼠只能吃硬度不大于当前体力值的奶酪。 老鼠从当前格到上下左右相邻的无障碍物的格需要时间1单位,有障碍物的格不能走。走到工厂上时即可吃到该工厂的奶酪,吃奶酪时间不计。问吃遍所有奶酪最少用时

输入

第一行三个整数H(1 <= H <= 1000)、W(1 <= W <=1000)、N(1 <= N <= 9),之后H行W列为地图, "."为空地, "X"为障碍物,"S"为老鼠洞,N表示有N个生产奶酪的工厂,硬度为1-N。

输出

输出一个整数,代表老鼠吃遍所有奶酪的最少时间花费。

输入样例
输入样例 1
3 3 1
S..
...
..1

输出样例1
4

输入样例 2
4 5 2
.X..1
....X
.XX.S
.2.X.

输出样例 2
12

输入样例 3
10 10 9
.X...X.S.X
6..5X..X1X
...XXXX..X
X..9X...X.
8.X2X..X3X
...XX.X4..
XX....7X..
X..X..XX..
X...X.XX..
..X.......

输出样例 3
91

解析:Bfs最短路问题.
值得一提的是:

  1. 这道题需要遍历n次最短路,从出发点 -> 硬度为1奶酪工厂最短路 -> 硬度为2奶酪工厂最短路 -> ... -> 硬度为3的奶酪工厂最短路。
  2. 在遍历图的时候,每一次bfs都要初始化所有路径为inf,这样可以判断这条路是否可达,或者之前是否走过,不过此题一定可以走完所有奶酪工厂,就不用担心不可以达的问题,而bfs第一次放入队列的数据肯定是该点的最短距离,所以之前走过,此时就不用再走。
  3. 是单独存放两个数据时可以用pair来存放,当存在两个多样类型数据时就可以封装成一个类,相对于结构数组美观一些。
    第一次这么呕心沥血写注释...

AC代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<string.h>
#include<stdlib.h>
#include<math.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> P; //用pair将两个数据合成一个数据(用结构体也可) 
const int num = 1005;
const long long inf = 0x3f3f3f3f;
int h, w, n; 
char maze[num][num]; //表示地图 
int sx, sy; //起点坐标 
int d[num][num]; //起点到该点的最短距离 
int dir[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; //右下左上四个方向移动的向量 
int res = 0; //最短时间 

bool cp(int xx, int yy)
{
	if(xx < 1 || xx > h || yy < 1 || yy > w) return false;
	else return true;
}

void bfs(int bgx, int bgy, int tar) //起点坐标, 目标工厂的奶酪硬度 
{
	queue<P> q; 
	memset(d, 0x3f3f, sizeof(d)); //将所有起点到该点的最短距离初始化为INF
	d[bgx][bgy] = 0; //起点到自身的距离为0
	q.push(P(bgx, bgy));
	//q.push(make_pair(bgx, bgy));
	while(q.size())
	{
		P now = q.front(); //将队列的第一个元素取出 
		q.pop(); //将队列的第一个元素弹掉
		int x = now.first, y = now.second; //将当前位置用x, y表示
		if(maze[x][y] - '0' == tar)
		{
			//重新赋值起点位置, 也就是之前目标工厂的位置 
			sx = x;
			sy = y;
			res += d[x][y]; //加上这次走的时间(距离) 
			return; 
		}
		for(int i = 0; i < 4; i++)
		{
			//下一次移动的位置坐标 
			int xx = x + dir[i][0];
			int yy = y + dir[i][1];
			if(cp(xx, yy) && maze[xx][yy] != 'X' && d[xx][yy] == inf) //bfs第一次访问到的点一定是最短的 
			{
				q.push(P(xx, yy)); //将其放入队列 
				d[xx][yy] = d[x][y] + 1; //到(xx, yy)的距离为到(x, y)距离 + 1 
			} 
		} 
	} 
} 

int main()
{
	scanf("%d%d%d", &h, &w, &n);
	getchar();
	for(int i = 1; i <= h ;i++)
	{
		for(int j = 1; j <= w; j++)
		{
			scanf("%c", &maze[i][j]);
			if(maze[i][j] == 'S')
			{
				sx = i;
				sy = j;
			}
		}
		getchar(); 
	}
	for(int i = 1; i <= n; i++)
		bfs(sx, sy, i); //从起点走到硬度为1的工厂再走到硬度为N的工厂 
	printf("%d\n", res);
	return 0;
}

标签:...,..,--,奶酪,yy,int,xx,Chesse,Aizu0558
来源: https://www.cnblogs.com/K2MnO4/p/13369940.html