题意
给定一张地图,表示我方和敌方2个人的地形布局,大炮间互相攻击,并且会影响3*3的区域,并且可以连带,问如果要摧毁所有敌方的大炮后,最多可以保留多少自己的大炮。
solution
分别对我方和敌方进行dfs求联通块数量,如果我方联通块更少,肯定输,输出-1。否则我们就用大炮数量最少联通块的去打对面的,这样能保证我们每次损失的大炮数量最少,敌方有b个联通块,因为我们先手,所以也只能打掉我们b-1个联通块,排序算第b-a大联通块大炮数量和就行。
#include <bits/stdc++.h> using namespace std; typedef long long ll; int m; char mp[20][105]; int vis[20][105]; int cnt; int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1}; int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1}; vector<int> v; void dfs(int x, int y) { for (int i = 0; i < 8; i++) { int fx = x + dx[i]; int fy = y + dy[i]; if (!vis[fx][fy] && mp[fx][fy] == '*') { cnt++; vis[fx][fy] = 1; dfs(fx, fy); } } } int main() { scanf("%d", &m); for (int i = 1; i <= 4; i++) scanf("%s", mp[i] + 1); for (int i = 11; i <= 14; i++) scanf("%s", mp[i] + 1); int cnt1 = 0, cnt2 = 0; for (int i = 1; i <= 4; i++) { for (int j = 1; j <= m; j++) { if (!vis[i][j] && mp[i][j] == '*') { vis[i][j] = 1; cnt1++; dfs(i, j); } } } for (int i = 10; i <= 14; i++) { for (int j = 1; j <= m; j++) { if (!vis[i][j] && mp[i][j] == '*') { cnt = 1; vis[i][j] = 1; cnt2++; dfs(i, j); v.push_back(cnt); } } } sort(v.begin(), v.end(), greater<int>()); if (cnt2 < cnt1) printf("-1\n"); else { while (--cnt1) v.pop_back(); int sum = 0; for (int i : v) sum += i; printf("%d\n", sum); } return 0; }