Atcoder #014 agc014_C BFS

LINK

 

题意:给定起点和最大操作次数$k$,地图'#'为上锁房间, 每次可以走$k$步,并任意解锁$k$个房间,问到达地图边界的最小次数。

思路:其实上锁与否并没有关系,因为先把$k$步走的次数用完, 剩下的就是解锁→走的步骤了。对于地图上的任意一点,其所需次数$ans$,设离地图边界最小的那一条的长度$d$,$ans=\lceil\frac{d}{k}\rceil$  所以BFS一下把起始所有能到达的点都考虑一遍就好了。

 

 

/** @Date    : 2017-05-07 19:07:12
  * @FileName: C BFS 贪心.cpp
  * @Platform: Windows
  * @Author  : Lweleth (SoundEarlf@gmail.com)
  * @Link    : https://github.com/Lweleth
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

char mp[1000][1000];
int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int vis[1000][1000];
int n, m, k;
int bfs(int sx, int sy)
{
	MMF(vis);
	int ans = INF;
	queueq;
	q.push(MP(sx, sy));
	while(!q.empty())
	{
		PII nw = q.front();
		q.pop();
		int sp = min(min(nw.fi - 1, nw.se - 1), min(n - nw.fi , m - nw.se));
		ans = min(sp / k + ((sp%k)?1:0), ans);
		for(int i = 0; i < 4; i++)
		{
			int nx = nw.fi + dir[i][0];
			int ny = nw.se + dir[i][1];
			if(nx > 0 && ny > 0 && nx <= n && ny <= m && mp[nx][ny] == '.')
			{
				if(!vis[nx][ny] && abs(nx - sx) + abs(ny - sy) <= k)
					vis[nx][ny] = 1, q.push(MP(nx, ny));
			}
		}
	}
	return ans;
}

int main()
{
	while(cin >> n >> m >> k)
	{
		getchar();
		int sx = -1, sy = -1;
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= m; j++)
			{
				scanf("%c",&mp[i][j]);
				if(mp[i][j] == 'S')
					sx = i, sy = j;
			}
			getchar();
		}	
		int ans = bfs(sx, sy);
		printf("%d\n", ans + 1);
	}
    return 0;
}
posted @ 2017-05-07 20:05  Lweleth  阅读(373)  评论(0编辑  收藏  举报