Atcoder #014 agc014_C BFS
题意:给定起点和最大操作次数$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; }