描述
“ACKing”同学以前做一个图像处理的项目时,遇到了一个问题,他需要摘取出图片中某个黑色线圏成的区域以内的图片,现在请你来帮助他完成第一步,把黑色线圏外的区域全部变为黑色。
图1 图2
已知黑线各处不会出现交叉(如图2),并且,除了黑线上的点外,图像中没有纯黑色(即像素为0的点)。
-
输入
-
第一行输入测试数据的组数N(0<N<=6)
每组测试数据的第一行是两个个整数W,H分表表示图片的宽度和高度(3<=W<=1440,3<=H<=960)
随后的H行,每行有W个正整数,表示该点的像素值。(像素值都在0到255之间,0表示黑色,255表示白色)
输出
- 以矩阵形式输出把黑色框之外的区域变黑之后的图像中各点的像素值。 样例输入
-
1 5 5 100 253 214 146 120 123 0 0 0 0 54 0 33 47 0 255 0 0 78 0 14 11 0 0 0
样例输出
-
0 0 0 0 0 0 0 0 0 0 0 0 33 47 0 0 0 0 78 0 0 0 0 0 0
/*乍一看,不是迷宫,就不能用广搜了么?!嗯?! 这应该是算广搜里边最简单的一类了吧。。几乎没有任何特殊的技巧。 but。开始为什么没想到呢?不要光想着怎么把这个黑色线的路径标注出来,标出来有什么用啊???! 后来又想从所有0的点往外扩散,可是怎么区分那些在线内哪些在线外呢? 还不如直接从左上角开始,搜到不是0的点,就改成0,然后入队。对于0点,直接不入队。 可是0不入队,它周围一圈的不管线内线外,不也不能被扩散到了么? 谁说的?!线外的从0点扩散不到,从别的非0点肯定能扩散到啊!毕竟它只要在外围,上下左右中肯定至少有一个方向的点非0。 所以,0点内的数,不管从哪个点,哪个方向,都进入不到,因为有0挡着,只要是外边一圈0,就没有扩散到里边的可能。 然后还有一点就是这个左上角。wa了好几次T T。。详见下。*/ #include <stdio.h> #include <queue> #include <string.h> using namespace std; typedef struct node { int x, y; }node; int m[965][1445], dirx[4] = {0,0,1,-1}, diry[4] = {1,-1,0,0}, w, h; void bfs(int x, int y) { int i; queue<node>q; node u, v; u.x = x; u.y = y; q.push(u); while(!q.empty()) { u = q.front(); q.pop(); for(i = 0 ; i < 4 ; i++) { v.x = u.x + dirx[i]; v.y = u.y + diry[i]; if(v.x > h+1 || v.x < 0 || v.y > w+1 || v.y < 0) //相应地,这里的范围也应该是整个大的 continue; if(m[v.x][v.y] == 0) continue; m[v.x][v.y] = 0; q.push(v); } } } int main() { int n, i, j; scanf("%d", &n); while(n--) { scanf("%d %d", &w, &h); for(i = 0 ; i <= h+1 ; i++) for(j = 0 ; j <= w+1 ; j++) m[i][j] = 1; for(i = 1 ; i <= h ; i++) for(j = 1 ; j <= w ; j++) scanf("%d", &m[i][j]); bfs(0, 0); //假如第一个点是0呢?不就不能入队了么。所以这里要保证是从一个非0点开始搜索。此题的技巧就在这里 for(i = 1 ; i <= h ; i++) { for(j = 1 ; j <= w ; j++) { if(j != w) printf("%d ", m[i][j]); //其实这里最后一个后面有空格也行,不过貌似时间要长一丢丢,我也不造为啥。。 else printf("%d\n", m[i][j]); } printf("\n"); } } return 0; }