CF35C Fire again 解题报告

CF35C Fire again 解题报告

1 题目链接

https://codeforces.com/problemset/problem/35/C

2 题目整理

题目 :再次着火

题目描述

在伯兰一场可怕的森林大火之后,一个森林再生计划开始实施。由于它N行,每行种植M棵树,是如此整齐,以至于人们可以将其映射到一个坐标系统中,因此第i行第j棵树的坐标为(i, j)。然而,一件可怕的事情发生了,年轻的森林着火了。现在我们必须找到最后着火的树的坐标来计划撤离。

燃烧同时在K个点开始,这意味着最初有K棵树开始燃烧。每一分钟,火就会从燃烧的树蔓延到不燃烧的树而这些树到最近燃烧的树的距离等于1。

找到最后一棵开始燃烧的树。如果有几个这样的树,则输出任意一个。

输入格式

第一行输入 N , M N,M N,M,——森林的大小。

第二行是一个整数 K K K,表示最开始着火的树木数量。

接下来 K K K行,每行有两个数 x i , y i x_i, y_i xi,yi,表示第 i i i棵最开始着火的数木坐标。

输出格式

输出一行两个数 X , Y X, Y X,Y,表示最后着火的数木的坐标。如果这样的树木有很多棵,输出其中任意一刻的坐标。

样例输入1
3 3
1
2 2
样例输出1
1 1
样例输入2
3 3
1
1 1
样例输出2
3 3
数据范围

对于 100 % 100\% 100%的数据:
1 ≤ N , M ≤ 2000 1 \leq N, M \leq 2000 1N,M2000
1 ≤ x i ≤ N 1 \leq x_i \leq N 1xiN
1 ≤ y i ≤ M 1 \leq y_i \leq M 1yiM
1 ≤ K ≤ 10 1 \leq K \leq 10 1K10

3 题意分析

3.1 题目大意

一个N行M列的网格中,有K个点。从这K个点出发,不停扩展到四周的格子。问最后被扩展到的格子的坐标。

3.2 样例分析

如上所述

4 解法分析

这题很明显是一道普通的广度优先搜索的题目,套模板即可。

AC代码

ACCode #001
// From xlk
// Rating 2428
// reason : 代码简洁,思路清晰
#include <bits/stdc++.h>
using namespace std;
int n, m, k, x, y;
int d[2020][2020];
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
int q[8000020], b, f;
bool in(int x, int y)
{
	return 1 <= x && x <= n && 1 <= y && y <= m;
}
int main()
{
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	cin >> n >> m >> k;
	memset(d, -1, sizeof d);
	for (int i = 0; i < k; i++)
	{
		cin >> x >> y;
		d[x][y] = 0;
		q[b++] = x;
		q[b++] = y;
	}
	while (f < b)
	{
		x = q[f++];
		y = q[f++];
		for (int i = 0; i < 4; i++)
		{
			int nx = x + dx[i];
			int ny = y + dy[i];
			if (in(nx, ny))
			{
				if (d[nx][ny] == -1)
				{
					d[nx][ny] = d[x][y] + 1;
					q[b++] = nx;
					q[b++] = ny;
				}
			}
		}
	}
	cout << x << ' ' << y << endl;
	return 0;
}
ACCode #002
// From rng_58
// Rating 3074
// reason : 思路清晰,代码简洁
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <functional>
#include <utility>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstdio>

using namespace std;

#define REP(i,n) for((i)=0;(i)<(int)(n);(i)++)
#define foreach(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)

#define INF (1<<29)

queue <int> q;
int dist[2010][2010];
int dx[]={1,-1,0,0},dy[]={0,0,1,-1};

void add(int x, int y, int d){
    if(d < dist[x][y]){
        dist[x][y] = d;
        q.push(x); q.push(y);
    }
}

int main(void){
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    
    int H,W,x,y,ansx=-1,ansy=-1,K,i,j;
    
    scanf("%d%d%d",&H,&W,&K);
    REP(i,H) REP(j,W) dist[i][j] = INF;
    REP(i,K){
        scanf("%d%d",&x,&y); x--; y--;
        add(x,y,0);
    }
    
    while(!q.empty()){
        x = q.front(); q.pop(); y = q.front(); q.pop();
        ansx = x; ansy = y;
        REP(i,4){
            int x2 = x + dx[i], y2 = y + dy[i];
            if(x2 >= 0 && x2 < H && y2 >= 0 && y2 < W) add(x2,y2,dist[x][y]+1);
        }
    }
    
    cout << ansx+1 << ' ' << ansy+1 << endl;
    
    return 0;
}
ACCode #003
// From Heart_Blue
// Rating 2425
// reason : 思路清晰,代码简洁
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
#include <cassert>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MEM(a,b) memset((a),(b),sizeof(a))
const LL INF = 1e9 + 7;
const int N = 2e3 + 10;
int dis[N][N];
int dx[] = { 0,0,-1,1 };
int dy[] = { 1,-1,0,0 };
int main()
{
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	MEM(dis, 0x3f);
	int n, m, k;
	cin >> n >> m >> k;
	queue<pair<int, int>> q;
	while (k--)
	{
		int x, y;
		cin >> x >> y;
		q.push({ x,y });
		dis[x][y] = 0;
	}
	pair<int, pair<int, int>> ans = { 0,{1,1} };
	while (!q.empty())
	{
		int x, y;
		tie(x, y) = q.front();
		q.pop();
		ans = max(ans, { dis[x][y],{x,y} });
		for (int i = 0; i < 4; i++)
		{
			int tx = x + dx[i];
			int ty = y + dy[i];
			if (tx < 1 || tx > n) continue;
			if (ty < 1 || ty > m) continue;
			if (dis[tx][ty] > dis[x][y] + 1)
			{
				dis[tx][ty] = dis[x][y] + 1;
				q.push({ tx,ty });
			}
		}
	}
	int x, y;
	tie(x, y) = ans.second;
	cout << x << ' ' << y << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值