luoguP1162填涂颜色
这道题刚开始打的暴力,64分。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 30;
int n, a[N][N], last[N];
int main () {
cin >> n;
for(int i = 0 ; i < n ; i ++)
for(int j = 0 ; j < n ; j ++)
scanf("%d", &a[i][j]);
for(int i = 0 ; i < n ; i ++) {
for(int j = n - 1; j >= 0 ; j --) {
if(a[i][j] == 1) {
last[i] = j;
break;
}
}
}
for(int i = 0; i < n ; i ++) {
bool flag = 0;
for(int j = 0 ; j <= last[i] ; j ++) {
if(a[i][j] == 1) flag = 1;
if(a[i][j] == 0 && flag == 1) a[i][j] = 2;
}
}
for(int i = 0 ; i < n ; i ++) {
for(int j = 0 ; j < n ; j ++) {
printf("%d ", a[i][j]);
}
printf("\n");
}
return 0;
}
不知道哪里出了错,开始想正解
没想出来然后看了题解没看懂(果然oier不适合看别人的代码)
但是大体思路了解了
广度优先搜索bfs
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 30;
int n, a[N][N], last[N];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
void bfs(int x, int y) {
if(x < 0 || x >= n || y < 0 || y >= n || a[x][y] == 1) return;
a[x][y] = 3;
for(int i = 0; i < 4; i ++) {
bfs(x + dx[i], y + dy[i]);
}
}
void print() {
for(int i = 0; i < n ; i ++) {
for(int j = 0 ; j < n ; j ++) {
if(a[i][j] == 3) printf("0 ");
else if(a[i][j] == 0) printf("2 ");
else printf("%d ", a[i][j]);
}
printf("\n");
}
}
void read() {
scanf("%d", &n);
for(int i = 0 ; i < n ; i ++)
for(int j = 0; j < n ; j ++)
scanf("%d", &a[i][j]);
}
int main() {
read();
bfs(0, 0);
print();
return 0;
}
然鹅把这份代码交上去,32分,还没有刚开始打的暴力高。
下载了样例发现如果一堆1和边界把整个矩形分成几部分,我们只能解决左上角的那部分,举个简单例子:
0 0 0 1 1 1 0 0
0 0 0 1 0 1 0 0
0 0 0 1 0 1 0 0
1 1 1 1 0 1 0 0
1 0 0 0 0 1 0 0
1 0 0 0 0 1 0 0
1 0 0 0 0 1 0 0
1 1 1 1 1 1 0 0
但是题解的代码没有问题。
(陷入思考)
发现边界问题很重要
把所有输入输出都调成1 = 1; i <= n
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 30;
int n, a[N][N], last[N];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
bool book[N][N];
void bfs(int x, int y) {
if(x < 0 || x > n || y < 0 || y > n || a[x][y] != 0||book[x][y] == 1) return;
book[x][y] = 1;
a[x][y] = 3;
for(int i = 0; i < 4; i ++) {
bfs(x + dx[i], y + dy[i]);
}
}
void print() {
// printf("********************\n");
for(int i = 1; i <= n ; i ++) {
for(int j = 1 ; j <= n ; j ++) {
if(a[i][j] == 3) printf("0 ");
else if(a[i][j] == 0) printf("2 ");
else printf("%d ", a[i][j]);
}
printf("\n");
}
}
void read() {
scanf("%d", &n);
for(int i = 1 ; i <= n ; i ++)
for(int j = 1; j <= n ; j ++)
scanf("%d", &a[i][j]);
}
int main() {
read();
bfs(0, 0);
print();
return 0;
}
发现一个破绽,即使输入输出的时候用了1到n,在矩阵的上下左右都留出了一列0,但是在搜索的时候只用到了左边和上面边界为0来绕过这堵墙,右面和下边还是没有用到。
最终!
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 32;
int n, a[N][N], last[N];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
bool book[N][N];
void bfs(int x, int y) {
if(x < 0 || x > n + 1|| y < 0 || y > n + 1|| a[x][y] != 0||book[x][y] == 1) return;
book[x][y] = 1;
a[x][y] = 3;
for(int i = 0; i < 4; i ++) {
bfs(x + dx[i], y + dy[i]);
}
}
void print() {
// printf("********************\n");
for(int i = 1; i <= n ; i ++) {
for(int j = 1 ; j <= n ; j ++) {
if(a[i][j] == 3) printf("0 ");
else if(a[i][j] == 0) printf("2 ");
else printf("%d ", a[i][j]);
}
printf("\n");
}
}
void read() {
scanf("%d", &n);
for(int i = 1 ; i <= n ; i ++)
for(int j = 1; j <= n ; j ++)
scanf("%d", &a[i][j]);
}
int main() {
read();
bfs(0, 0);
print();
return 0;
}
这段代码和上一段唯一的区别就是把dfs里面的“判断边界”x > n || y > n
改成了x > n + 1 || y > n + 1
使搜索的时候在右面和下面也可以绕过这堵墙。
最终AC了。
真是一波三折搞人心态。