数组的边缘检测问题《一》

题目描述
 Ada不喜欢学数字,却喜欢玩游戏,看着她的小手指在手机屏上戳来戳去,顿时感觉祖国的游戏事业有了未来.
最近她喜欢上清障碍的一款游戏.
游戏是一个5行4列的方格阵列,有些格子有障碍物,有些没有,过关是要求所有的障碍物被清除.Ada只能在没有障碍物的格子放置炸弹, 炸弹会清除东南西北四个方向上的相邻格子的障碍物. 也就是,如果无障碍物的格子座标是(x,y), 则(x+1, y),(x-1,y),(x,y+1),(x,y-1)四个相邻格的障碍物(如果有的话)都会清除, 座标越界的情况不需要考虑.
为了挽救沉迷游戏的Ada, 规定Ada每过一关必须用最少的炸弹,否则就收缴手机让她没得玩. 如下图的局面(阴影表示障碍),只需要一个炸弹即可

显然Ada处理不了这么复杂的问题,帮帮她吧。

1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
result:1 

1 1 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
result:2

1 0 1 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
result:1

分析:

首先读入地图,将障碍置为1,然后依次检验每个障碍周围的可爆破点,计算可爆破点的权值。如果一次只能清除一个障碍则权重为1,否则依次加权,最后将障碍点周围的所有可爆破点的权值都计算出来,求其最大权值位置,将此爆破点爆破,然后顺带清理周围障碍(即周围上下左右的坐标点值置为0),炸弹数加一,依次遍历整个地图,直到最后一个点。

缺点:

计算比较复杂,每次检测爆破点时都需要重复计算周围所有的点;当障碍清理完成,地图未遍历完时还需要继续遍历消耗时间。

代码:

#include <iostream>

using namespace std;

//计算坐标点上下左右的权值
int findobstacle(int (&map)[5][4], int h, int w, int x, int y)//输入地图\边缘位置\以及坐标点
{
	int score = 0;
	
	if ((x+1 <h)&&(map[x+1][y]==1))//左障碍检测
	{
		score += 1;
	}

	if ((x - 1 >=0) && (map[x - 1][y] == 1))//右障碍检测
	{
		score += 1;
	}

	if ((y + 1 < w) && (map[x][y+1] == 1))//下障碍检测
	{
		score += 1;
	}

	if ((y - 1 >=0) && (map[x][y-1] == 1))//上障碍检测
	{
		score += 1;
	}
	return score;//返回权值
}

//清障函数
void Zeroobstacle(int(&map)[5][4], int h, int w, int x, int y)
{
	if (x + 1 < h)//左障碍
	{
		map[x + 1][y] = 0;
	}

	if (x - 1 >=0)//右障碍
	{
		map[x - 1][y] = 0;
	}

	if (y + 1 < w)//下障碍
	{
		map[x][y+1] = 0;
	}

	if (y - 1 >= 0)//上障碍
	{
		map[x][y - 1] = 0;
	}
	return;

}


//递归查找最大值
int findmax(int *a,int n)
{
	int m;
	if (n == 1)
		return a[0];
	else
	{
		m = findmax(a, n - 1);
		return a[n - 1] >= m ? a[n - 1] : m;
	}
}



int main()
{
	//地图样式
	int map[5][4]{
	{ 1, 0, 1, 0 },
	{ 1, 1, 0, 1 }, 
	{ 0, 1, 0, 0 }, 
	{ 0, 0, 0, 0 }, 
	{ 0, 0, 0, 0 }};


	int boomnum = 0;//炸弹数


	for (int i = 0; i < 5; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			
			//检测障碍
			if (map[i][j] == 1)
			{
				//寻找完美爆破点
				int score[4]{0};
				if ((j+1<4)&&(map[i][j+1]!=1))//检测右边
				{
					score[0] = findobstacle(map, 5, 4, i, j + 1);
				}
				
				if ((j - 1>0) && (map[i][j-1] != 1))//检测左边
				{
					score[1] = findobstacle(map, 5, 4, i, j - 1);
				}

				if ((i - 1>0) && (map[i-1][j] != 1))//检测上边
				{
					score[2] = findobstacle(map, 5, 4, i-1, j);
				}

				if ((i + 1<5) && (map[i+1][j] != 1))//检测下边
				{
					score[3] = findobstacle(map, 5, 4, i + 1, j);
				}
				
				int num = findmax(score, 4);//取最优权重
				if (num != 0 && num == score[0])//最优爆破点在右
				{
					Zeroobstacle(map, 5, 4, i, j + 1);
					boomnum += 1;//炸弹+1
					continue;
				}
				else if (num != 0 && num == score[1])//最优爆破点在左
				{
					Zeroobstacle(map, 5, 4, i, j - 1);
					boomnum += 1;//炸弹+1
					continue;
				}
				else if (num != 0 && num == score[2])//最优爆破点在上
				{
					Zeroobstacle(map, 5, 4, i-1, j);
					boomnum += 1;//炸弹+1
					continue;
				}
				else if (num != 0 && num == score[3])//最优爆破点在下
				{
					Zeroobstacle(map, 5, 4, i + 1, j);
					boomnum += 1;//炸弹+1
					continue;
				}
				else
				{
					map[i][j] = 0;//右边跟下边都是障碍 直接清除这个点
					boomnum += 1;//炸弹+1
					continue;
				}

			}
		}
	}

	cout << "Boom num:" << boomnum << endl;
	system("pause");
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值