intmain(){ cin >> n >> m; for (int i = 0; i < n; i ++) { char c; for (int j = 0; j < m; j ++) { cin >> c; // 将地形储存为二进制 if (c == 'P') mp[i] = mp[i] * 2; else mp[i] = mp[i] * 2 + 1; } }
// 记录一个二进制数含有几个1 for (int i = 1; i < (1 << m); i ++) // cnt[i]存的是作为一个二进制数有几个一 cnt[i] = cnt[i >> 1] + (i & 1); // 记录有效的地形 for (int r = 0; r < (1 << m); r ++) { // 相邻两格不能重复 if (((r >> 1) & r) == 0) // 相邻三个格子只能有一个,所以位移两位再取“与” if (((r >> 2) & r) == 0) { // 用v记录所有的有效单行布局 v.push_back(r); } }
for (int i = n - 1; i >= 0; i --) { // 穷举在有效地形内的s for (int x = 0; x < v.size(); x ++) { int s = v[x]; // 穷举在有效地形内的t for (int y = 0; y < v.size(); y ++) { int t = v[y]; // 当s,t同时可以存在时 if ((s & t) == 0) { // 穷举这一行的所有地形 for (int z = 0; z < v.size(); z ++) { int r = v[z]; // 这一行地形不可以与前一行同列 if ((r & s) == 0) // 这一行地形不可以与上上行同列 if ((r & t) == 0) // 这一地形必须与地图匹配(地形) if ((r & mp[i]) == 0) // 使用滚动数组更新答案(否则MLE会爆) f[i % 2][s][t] = max(f[i % 2][s][t], f[(i + 1) % 2][r][s] + cnt[r]); } } } } } // 答案为穷举第二,第三行所有地形情况下的放炮总数 int ans = 0; for (int i = 0; i < v.size(); i ++) { int s = v[i]; for (int j = 0; j < v.size(); j ++) { int t = v[j]; ans = max(ans, f[0][s][t]); } } cout << ans << endl; return0; }