测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

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; }
上一题 下一题