Codeforces Round #297 (Div. 二) - D. Arthur and Walls (判断矩形)
Codeforces Round #297 (Div. 2) -- D. Arthur and Walls (判断矩形)
思路:我自己一开始想的是dfs,每次搜出一个路径上的最上最下最左最右,然后在这个矩形内全赋值为‘.’,后来发现这样太慢了,各种回溯,TLE了,会有很坑爹很坑爹的数据,然后看了某些人的做法,发现很好玩,就是去找每个2 * 2矩形上可以组成
.. ..
.* 或 *.
或者与其类似的情况,然后用队列模拟
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cassert> using namespace std; char a[2005][2005]; int n, m; bool check(int x, int y) { if(a[x][y] == '.' || x < 1 || y < 1 || x > n || y > m) return 0; if(a[x][y - 1] == '.' && a[x - 1][y - 1] == '.' && a[x - 1][y] == '.') return 1; if(a[x][y + 1] == '.' && a[x - 1][y + 1] == '.' && a[x - 1][y] == '.') return 1; if(a[x][y - 1] == '.' && a[x + 1][y - 1] == '.' && a[x + 1][y] == '.') return 1; if(a[x][y + 1] == '.' && a[x + 1][y + 1] == '.' && a[x + 1][y] == '.') return 1; return 0; } int main() { scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%s", a[i] + 1); } queue<pair<int , int> > q; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { if(check(i, j)) q.push(make_pair(i, j)); } } while(!q.empty()) { int i = q.front().first; int j = q.front().second; q.pop(); if(!check(i, j)) continue; a[i][j] = '.'; for(int x = -2; x <= 2; x++) { for(int y = -2; y <= 2; y++) { if((x || y) && check(i + x, j + y)) q.push(make_pair(i + x, j + y)); } } } for(int i = 1; i <= n; i++) { printf("%s\n", a[i] + 1); } return 0; }
我的TLE代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #define LL long long using namespace std; char map[2005][2005]; char tmp[2005]; int vis[2005][2005]; int n, m, ans; int xx[4] = {0, 1, 0, -1}; int yy[4] = {1, 0, -1, 0}; int r, l, up, down;//最右最左最上最下 void dfs(int a, int b) { if(a <= 0 || a > n || b <= 0 || b > m) return; if(map[a][b] == '*') return; up = max(up, a); down = min(down, a); r = max(r, b); l = min(l, b); vis[a][b] = 1; for(int i = 0; i < 4; i++) { if(!vis[a + xx[i]][b + yy[i]]) dfs(a + xx[i], b + yy[i]); } vis[a][b] = 0; } void fun() { for(int i = down; i <= up; i++) { for(int j = l; j <= r; j++) { map[i][j] = '.'; } } } int main() { scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%s", tmp); int len = strlen(tmp); for(int j = 0; j < len; j++) { map[i][j + 1] = tmp[j]; } map[i][len + 1] = '\0'; } ans = 0; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { if(!vis[i][j] && map[i][j] != '*') { r = l = j; up = down = i; dfs(i, j); fun(); } } } for(int i = 1; i <= n; i++) printf("%s\n", map[i] + 1); return 0; }
- 1楼u0142478061小时前
- 楼主,你的TLE代码为什么要回溯?不是处理完一个联通块之后就可以不用管它了吗?
- Re: u01435548018分钟前
- 回复u014247806n上面的数据是5*5的,为什么提交后就变成一行了╮(╯▽╰)╭
- Re: u01435548016分钟前
- 回复u014247806n给你看个数据估计就好了,比如n....*n***.*n*.*.*n*.***n*....n这样如果不回溯就会输出n....*n.....n.....n.....n.....n这里的下一个连通块可能影响上一个连通块,我WA了一下才发现的,改了下,多个回溯又TLE了,所以我这个姿势不太对,太慢了,哎,还得多做做题呀