Cheese Aizu-0558(BFS)

3 篇文章 0 订阅

チーズ ()

問題

今年も JOI 町のチーズ工場がチーズの生産を始め,ねずみが巣から顔を出した.JOI 町は東西南北に区画整理されていて,各区画は巣,チーズ工場,障害物,空き地のいずれかである.ねずみは巣から出発して全てのチーズ工場を訪れチーズを 1 個ずつ食べる.

この町には,N 個のチーズ工場があり,どの工場も1種類のチーズだけを生産している.チーズの硬さは工場によって異なっており,硬さ 1 から N までのチーズを生産するチーズ工場がちょうど 1 つずつある.

ねずみの最初の体力は 1 であり,チーズを 1 個食べるごとに体力が 1 増える.ただし,ねずみは自分の体力よりも硬いチーズを食べることはできない.

ねずみは,東西南北に隣り合う区画に 1 分で移動することができるが,障害物の区画には入ることができない.チーズ工場をチーズを食べずに通り過ぎることもできる.すべてのチーズを食べ終えるまでにかかる最短時間を求めるプログラムを書け.ただし,ねずみがチーズを食べるのにかかる時間は無視できる.

入力

入力は H+1 行ある.1 行目には 3 つの整数 H,W,N (1 ≤ H ≤ 1000,1 ≤ W ≤ 1000,1 ≤ N ≤ 9) がこの順に空白で区切られて書かれている.2 行目から H+1 行目までの各行には,'S','1', '2', ..., '9','X','.' からなる W 文字の文字列が書かれており,各々が各区画の状態を表している.北から i 番目,西から j 番目の区画を (i,j) と記述することにすると (1 ≤ i ≤ H, 1 ≤ j ≤ W),第 i+1 行目の j 番目の文字は,区画 (i,j) が巣である場合は 'S' となり,障害物である場合は 'X' となり,空き地である場合は '.' となり,硬さ 1, 2, ..., 9 のチーズを生産する工場である場合はそれぞれ '1', '2', ..., '9' となる.入力には巣と硬さ 1, 2, ..., N のチーズを生産する工場がそれぞれ 1 つずつある.他のマスは障害物または空き地であることが保証されている.ねずみは全てのチーズを食べられることが保証されている.

出力

すべてのチーズを食べ終えるまでにかかる最短時間(分)を表す整数を 1 行で出力せよ.

入出力例

入力例 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

問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

 

咱也看不懂。。但也不敢问。。只能用翻译了hhh


题意应该是从起点S开始
到1、2、3....n的最短距离(因为他说老鼠不能吃比自己体力大的)
 输入:第一行三个整数H(1 <= H <= 1000)、W(1 <= W <=1000)、N(1 <= N <= 9),之后H行W列为地图, “.“为空地, ”X“为障碍物,”S“为老鼠洞, 1-N代表硬度为1-N的奶酪的工厂。输出最少用时。
*

//Cheese Aizu - 0558 
#include <iostream>
#include <queue>
#include <cstring>

using namespace std;

char MAP[1005][1005];//地图
int vis[1005][1005]; 
int dir[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};//方向向量 
int h,w,n,head,sum=0;

struct Node{
	int x;
	int y;
	int step;
};

bool check(Node s){//约束条件检验 
	if(s.x>=0 && s.x<h && s.y>=0 && s.y<w && MAP[s.x][s.y]!='X' && !vis[s.x][s.y]){
		return 1;
	} else return 0;
}

//每次bfs的起点都不同,这次bfs的终点要被记录为下次bfs的起点
void bfs(Node &s){//引用传递 
	memset(vis,0,sizeof(vis));
	queue<Node> q;
	Node now,next;//定义两个状态,当前和下一个 
	s.step = 0;//计数器清零
	q.push(s);//起点入队
	vis[s.x][s.y] = 1;//标记访问
	
	while(!q.empty()){
		now = q.front();//取队首元素进行扩展
		q.pop();
		
		if(MAP[now.x][now.y] - '0' == head){
			sum += now.step;
			s.x = now.x;
			s.y = now.y;
			return;
		}
		
		for(int i=0; i<4; i++){
			next.x = now.x + dir[i][0];
			next.y = now.y + dir[i][1];
			
			if(check(next)){//如果下一个状态满足约束条件 
				next.step = now.step + 1;
				q.push(next);//入队 
				vis[next.x][next.y] = 1;//标记访问 	
			}
		}		
	} 
	 
}
int main(void)
{
	memset(vis,0,sizeof(vis));	
	cin >> h >> w >> n;
	Node start;
	for(int i=0; i<h; i++){
		for(int j=0; j<w; j++){
			cin >> MAP[i][j];
			if(MAP[i][j] == 'S'){
				start.x = i;
				start.y = j;
			}
		}
	}
	
	sum = 0;
	head = 1;
	
	for(int i=0; i<n; i++){
		bfs(start);
		head++;
	}	
	cout << sum << endl;
		
	return 0;
}

/*
题意应该是从起点S开始
到1、2、3....n的最短距离
 输入:第一行三个整数H(1 <= H <= 1000)、W(1 <= W <=1000)、N(1 <= N <= 9),之后H行W列为地图, “.“为空地, ”X“为障碍物,”S“为老鼠洞, 1-N代表硬度为1-N的奶酪的工厂。输出最少用时。
*/

/*题意:
今年,JOI町的奶酪工厂开始生产奶酪,老鼠从巢中探出头来。JOI町在东西南北进行划分整理,各区划为巢、奶酪工厂、障碍物、空地之一。老鼠从巢出发,访问所有的奶酪工厂,一个地吃奶酪。

这个城市有N个奶酪工厂,每个工厂都只生产一种奶酪。奶酪的硬度因工厂而异,正好有一个生产从1到N的奶酪的干酪工厂。

老鼠最初的体力是1,每吃一个奶酪体力就会增加1。但是,老鼠不能吃比自己的体力还硬的奶酪。

老鼠可以在东西南北相邻的区划内移动1分钟,但不能进入障碍物的区划。也可以不吃芝士工厂而通过。请写出寻求吃完所有奶酪所需的最短时间的程序。但是,老鼠吃奶酪所花的时间可以忽略不计。

输入
输入内容为H+1行。第1行中以空格分隔的3个整数H,W,N(1 H 1000,1 W 1000,1 N 9)由空格分隔。从第2行到第H+1行,每一行都按照“S”,“1”,‘2’,.,‘9’,‘X’,‘.’‘写下,“S”,’1‘,’2‘,.,’9‘,’X‘,’.‘组成的W字符串,每个文字都表示各分区的状态。如果将从北部开始的第i个、从西开始的第j个区段记作(i,j)(1 i H,1 j W),第i+1行的第j个字符,在地块(i,j)为巢时为‘S’,如果是障碍物,则为“X”;如果是空地,则为“.”,生产硬度为1,2,.,9的干酪的工厂,分别为‘1’,‘2’,.,‘9’。在输入时,巢和硬度为1,2,.,生产N个奶酪的工厂各有1个。其他格子可以保证是障碍物或空地。老鼠可以保证可以吃到所有的奶酪。

输出
输出一个整数,表示吃完所有奶酪所花费的最短时间(分钟)。
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值