A38976. 简易炸弹超人
填空题
中等
知识点
题目描述
简易炸弹超人
题目描述
有一块矩形游戏场地,场地被分成N×M的网格(4≤N≤100 ,4≤M≤10),其中一部分小方格是水域,另一部分小方格是陆地。
为防御敌军攻击,玩家需要在游戏场地安置炸弹:
1. 炸弹只能安置在陆地上;
2. 每颗炸弹爆炸后,可以波及到炸弹所在的小方格,及相邻的上、下、左、右小方格;
3. 任意两颗炸弹爆炸后不能波及到同一个小方格。
请帮助玩家计算出如何安置炸弹,可以使炸弹波及到的范围最大,输出最多可以波及到的小方格数量。
例如:N=4,M=4,网格中水域和陆地的情况如图1所示:

图中,蓝色区域代表水域,绿色区域代表陆地;安置炸弹的最优方案之一如图2所示;炸弹波及的范围如图3所示(黑色区域)。
这块4×4的矩形游戏场地最多可以波及到11个小方格,其他方案都不会优于这个结果
输入格式
第一行输入两个正整数N和M(4≤N≤100 ,4≤M≤10 ),分别表示网格的行数和列数,两个正整数之间以一个空格隔开
接下来输入N行,每行M个字符(字符只能是大写字母A或B),A表示水域,B表示陆地,字符之间以一个空格隔开.
输出格式
输出一个整数,表示最多可以波及到的小方格数量
样例输入
4 4
B A A A
A B A B
B A B B
A B A A
样例输出
11
参考答案
#include <iostream>
#include <vector>
using namespace std;
const int N = 110, M = 1 << 10;
int n, m, g[N], cnt[M], f[2][M][M];
vector<int> s, h[M];
bool check(int s) {
return !(s & s >> 1 || s & s >> 2);
}
bool check2(int s) {
return s & s >> 1;
}
int count(int x, int s) {
int cnt = 0, flag = 0;
for (int i = 0; i < m; i++)
if (s >> i & 1) {
flag = 1;
if (x - 1 >= 1) cnt++;
if (x + 1 <= n) cnt++;
if (i - 1 >= 0) cnt++;
if (i + 1 < m) cnt++;
}
return cnt + flag;
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 0; j < m; j++) {
char x;
cin >> x;
if (x == 'A') g[i] += 1 << j;
}
for (int i = 0; i < 1 << m; i++)
if (check(i)) s.push_back(i);
// 筛取在行上合法的状态
for (int i = 1; i <= n + 2; i++)
for (int j = 0; j < s.size(); j++) // 第i行
for (int k = 0; k < s.size(); k++) // 第i-1行
for (int u = 0; u < s.size(); u++) // 第i-2行 {
int a = s[u], b = s[k], c = s[j];
if ((a & b) || (b & c) || (a & c)) continue;
if ((g[i] & c) || (g[i - 1] & b)) continue;
if (check2(a | b)) continue;
int cnt = i <= n ? count(i, c) : 0;
f[i & 1][j][k] = max(f[i & 1][j][k], f[i - 1
& 1][k][u] + cnt);
}
cout << f[n + 2 & 1][0][0] << endl;
return 0;
}
上一题
下一题