题目:

2个4*n的图,表示后手和先手部署炮台的方案。问先手那方在消灭后手所有炮台的条件下最多能保留自己多少炮台。


做法:

先求出后手和先手炮台联通块数量
,无解。
否则,由于先手每次打击后必定暴露一个联通块。我们贪心选择暴露炮塔数量少的联通块就行了。
所以先手方最多能保留最大的个联通块中的炮台数。


代码:

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define debug(a) cout << #a ": " << a << endl
using namespace std;
typedef long long ll;
const int N = 110;
char s[5][N];
int n, col[5][N], color, clor_cnt;
vector<int> v;
void dfs(int x, int y){
    col[x][y] = color;
    clor_cnt++;
    for (int i = -1; i <= 1; ++i){
        for (int j = -1; j <= 1; ++j){
            if (i == 0 && j == 0) continue;
            int tx = x+i, ty = y+j;
            if (tx < 1 || tx > 4 || ty < 1 || ty > n || s[tx][ty] != '*' || col[tx][ty]) continue;
            dfs(tx, ty);
        }
    }
}
int main(void){ 
    IOS;
    cin >> n;
    for (int i = 1;  i<= 4; ++i){
        cin >> (s[i]+1);
    }
    int tgt_num = 0;
    for (int i = 1; i <= 4; ++i){
        for (int j = 1; j <= n; ++j){
            if (s[i][j] == '*' && !col[i][j]){
                color++, clor_cnt = 0;
                dfs(i, j);
                tgt_num++;
            }
        }
    }
    memset(col, 0, sizeof col);
    color = 0;
    for (int i = 1; i <= 4; ++i){
        cin >> (s[i]+1);
    }
    for (int i = 1; i <= 4; ++i){
        for (int j = 1; j <= n; ++j){
            if (s[i][j] == '*' && !col[i][j]){
                color++, clor_cnt = 0;
                dfs(i, j);
                v.push_back(clor_cnt);
            }
        }
    }
    if (v.size() < tgt_num){
        cout << -1 << endl;
    }else{
        sort(v.begin(), v.end(), greater<int>());
        int ans = 0;
        for (int i = 0; i < v.size()-tgt_num+1; ++i){
            ans += v[i];
        }
        cout << ans << endl;
    }
    return 0;
}