【每日一题】28. 模拟战役 (模拟 + DFS/BFS/并查集)

补题链接:Here

本题属于一道模拟题

虽然这题介绍一大堆,总结起来就是几句话,给出地图n列,前4行是a的地盘,后四行是b的地盘,每个人地盘上面有星号代表大炮。
大炮会 3 * 3的波及周围,会一直传递,b先手,a立刻反击b出手的大炮,问b能不能消灭a全部的大炮,如果能最后剩余最大大炮数是几。
那么很显然,我们发现a处于究极被动方,b是无敌主动方,我们通过方便一次跑图,把攻击一个地方,波及到周边的大炮都合并到一个点去。
我们发现如果a最后的点数大于b的点数,那么b永远消灭不完a,输出-1。
否则,对于b来说,反正我都要把你a消灭干净,谁先谁后没得关系。但是出手的大炮却可以控制,把一个点上大炮数量最少的拉上去当炮灰,先死。
最后留下的一定大炮总数就是最大的了。

const int N = 110;
string g[10];
int a[N], b[N];
int cnta, cntb, cnt;
int n;
void dfs(int x, int y, int Edge) { // Edge边界
	if (g[x][y] == '.')return ;
	g[x][y] = '.', cnt++;
	for (int i = -1; i <= 1; ++i)
		for (int j = -1; j <= 1; ++j)
			if (!i and !j)continue;
			else {
				int dx = x + i, dy = y + j;
				if (dx >= Edge and dx < 4 + Edge and dy >= 0 and dy < n)
					dfs(dx, dy, Edge);
			}
}
void solve() {
	cin >> n;
	for (int i = 0; i < 8; ++i)cin >> g[i];
	for (int i = 0; i < 4; ++i)
		for (int j = 0; j < n; ++j)
			if (g[i][j] == '*') {
				cnt = 0;
				dfs(i, j, 0);
				a[++cnta] = cnt;
			}
	for (int i = 4; i < 8; ++i)
		for (int j = 0; j < n; ++j)
			if (g[i][j] == '*') {
				cnt = 0;
				dfs(i, j, 4);
				b[++cntb] = cnt;
			}
	if (cnta > cntb) {cout << "-1\n"; return ;}
	sort(b + 1, b + 1 + cntb);
	int ans = 0;
	for (int i = cnta; i <= cntb; ++i)ans += b[i];
	cout << ans << "\n";
}
posted @ 2021-05-18 20:34  Koshkaaa  阅读(95)  评论(0编辑  收藏  举报