nyoj 92 图像有用区域

点击打开链接

图像有用区域

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 4
描述

“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
典型的搜索题,我不知道别人怎么解决的,我是用了很朴素的办法,就是找图形的上下左右四个边界上的非0点,如果找到一个,就从这个点开始广搜,直到边上都为0,那么剩下的点就是截取的区域
#include<stdio.h>
#include<string.h>
int map[970][1450];
int queue[1384801][2];
int head , tail;
int x , y;
int start_x , start_y;
void step(int a, int b)
{
	if(a > 0 && map[a - 1][b] != 0 )//&& haxi[a - 1][b] == 0)
	{
		map[a - 1][b] = 0;
		queue[tail][0] = a -1;
		queue[tail++][1] = b;
	}
	if(a < x - 1 && map[a + 1][b] != 0)// && haxi[a + 1][b] == 0)
	{
		map[a + 1][b] = 0;
		queue[tail][0] = a +1;
		queue[tail ++][1] = b;
	}
	if(b > 0 && map[a][b - 1] != 0 )//&& haxi[a][b - 1] == 0)
	{
		map[a][b - 1] = 0;
		queue[tail][0] = a;
		queue[tail++][1] = b - 1;
	}
	if(b < y - 1 && map[a][b + 1] != 0 )//&& haxi[a][b + 1] == 0)
	{
		map[a][b + 1] = 0;
		queue[tail][0] = a;
		queue[tail++][1] = b + 1;
	}
}
int search_point()
{
	int i ;	
	for(i = 0 ; i < x ; i++) 
	{	
		if(map[i][0] != 0)	
		{		
			start_x = i;	
			start_y = 0;
			break;
		}
		if(map[i][y - 1] != 0)	
		{
			start_x = i;
			start_y = y - 1;
			break;		
		}	
	}
	if(i == x) //×óÓÒûÕÒµ½ÔÙÕÒÉÏϱ߽ç		
	{
		for(i = 0 ; i < y ; i++)
		{
			if(map[0][i] != 0)	
			{
				start_x = 0;
				start_y = i;	
				break;
			}
			if(map[x - 1][i] != 0)
			{
				start_x = x - 1;
				start_y = i;
				break;	
			}		
		}
		if(i == y) 
			return 0;				
	}
	head = 0;
	tail = 1;
	queue[head][0] = start_x;
	queue[head][1] = start_y;
	map[start_x][start_y] = 0;
	for( ; head != tail ; head++)	
	{
		step(queue[head][0] , queue[head][1]);		
	}
	return 1;
}


int main()
{
	int i , j , k;
	int flag;

	scanf("%d" , &k);
	while(k--)
	{
		scanf("%d %d" , &y , &x);
		flag = 0;
		for(i = 0 ; i < x ; i++)
		{
			for(j = 0 ; j < y ; j++)
			{
				scanf("%d" , &map[i][j]);
				if(map[i][j] == 0)
					flag =1;
			}
				
		}
		if(flag == 1)
			while(search_point() != 0);
		for(i = 0 ; i < x ; i++)
		{
			for(j = 0 ; j < y ; j++)
			{
				printf("%d " , map[i][j]);
			}
		printf("\n");
		}
	}
	return 0;
}
        


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

勇敢的炮灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值