原题连接
- 题意:给出 (n leqslant) 和 (m leqslant 10) 行的矩阵,要求出来,炮兵能打到横竖打两格,然后要求最多放多少个炮兵。
- 题解:当发现尽管每行是 (2^m) 即最大是 (1024) 但是如果把限制加入,每行每个炮兵相邻不能小于 (2),所以预处理那么就会使得本来是 (1024) 变成 (64)。
有一种简单的方法判断是否是山地
还有一种简单的方法判断敌人是否在一起。
#include <iostream>
#include <vector>
using namespace std;
const int N = 110;
char mp[N][110];
int G[N];
vector<int>state;
int n, m;
int dp[2][N][N];
void init() {
for (int i = 0; i < (1 << m); i ++) {
bool f = 1;
for (int j = 0; j < m; j ++) {
if (i >> j & 1 && (i >> j + 1 & 1 || i >> j + 2 & 1 )) {
f = 0;
}
}
if (f)
state.push_back(i);
}
}
int cnt(int x) {
int ret = 0;
int X = x;
while (x) {
ret += x & 1;
x /= 2;
}
return ret;
}
void solve() {
cin >> n >> m;
for (int i = 1; i <= n; i ++) {
cin >> (mp[i]);
for (int j = 0; j < m; j ++) {
if (mp[i][j] == 'H')G[i] += 1 << j;
}
}
init();
int ans = -1;
//cout << state.size() << endl;
for (int i = 1; i <= n; i ++) {
for (int ii = 0; ii < state.size(); ii++) {
for (int jj = 0; jj < state.size(); jj++) {
for (int kk = 0; kk < state.size(); kk++) {
int a = state[ii], b = state[jj], c = state[kk];
if ( (a & b | b & c | a & c) ==0) {//炮兵们是否能攻击到
if ( (a & G[i] | b & G[i-1]) == 0) {//是否是合理放置
dp[i&1][ii][jj] = max(dp[i&1][ii][jj], dp[i-1&1][jj][kk] + cnt(a));
ans = max(ans, dp[i&1][ii][jj]);
// if (ans == 5){
// cout << i << " " << a << " " << b << " " << c << "?" << (b&c) << endl;
// cout << (a&b) << endl;
// cout << (a&c) << endl;
// cout << (b&c) << endl;
// cout << (0|9) << endl;
// cout << ((a & b) | (b & c) | (a & c)) << endl;
// }
}
}
}
}
}
}
cout << ans << endl;
}
int main() {
int t = 1;//cin >> t;
while (t--)solve();
return 0;
}