题意
给定一张地图,表示我方和敌方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;
}

京公网安备 11010502036488号