题目描述
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
using namespace std;
//计算坐标点上下左右的权值
int findobstacle(int (&map)[5][4], int h, int w, int x, int y)//输入地图\边缘位置\以及坐标点
{
int score = 0;
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;
}