【题解】ICPC2020上海 Mine Sweeper II【思维】
链接:https://codeforces.com/gym/102900/problem/B
B. Mine Sweeper II
time limit per test
1 second
memory limit per test
1024 megabytes
input
standard input
output
standard output
A mine-sweeper map X can be expressed as an n×mn×m grid. Each cell of the grid is either a mine cell or a non-mine cell. A mine cell has no number on it. Each non-mine cell has a number representing the number of mine cells around it. (A cell is around another cell if they share at least one common point. Thus, every cell that is not on the boundary has 8 cells around it.) The following is a 16×30 mine-sweeper map where a flagged cell denotes a mine cell and a blank cell denotes a non-mine cell with number 0.
Given two mine-sweeper maps A,B of size n×m, you should modify at most \(\left \lfloor \frac{nm}{2} \right \rfloor\) (i.e. the largest nonnegative integer that is less than or equal to \(\frac{nm}{2}\)) cells in B (from a non-mine cell to a mine cell or vice versa) such that the sum of numbers in the non-mine cells in A and the sum of numbers in the non-mine cells in B are the same. (If a map has no non-mine cell, the sum is considered as 0.)
If multiple solutions exist, print any of them. If no solution exists, print "-1" in one line.
Input
The first line contains two integers n,m(1≤n,m≤1000), denoting the size of given mine-sweeper maps.
The i-th line of the following nn lines contains a length-m string consisting of "." and "X" denoting the i-th row of the mine-sweeper map A. A "." denotes for a non-mine cell and an "X" denotes for a mine cell.
The i-th line of the following n lines contains a length-m string consisting of "." and "X" denoting the i-th row of the mine-sweeper map B. A "." denotes for a non-mine cell and an "X" denotes for a mine cell.
Output
If no solution exists, print "-1" in one line.
Otherwise, print nn lines denoting the modified mine-sweeper map B. The i-th line should contain a length-mm string consisting of "." and "X" denoting the i-th row of the modified map B. A "." denotes for a non-mine cell and an "X" denotes for a mine cell.
Please notice that you need not print the numbers on non-mine cells since these numbers can be determined by the output mine-sweeper map.
题目大意:
A和B两张不同的的扫雷图。把一个非雷的格子改为雷,或者把一个雷的格子改为非雷记为一次修改。要求对B进行\(\left \lfloor \frac{nm}{2} \right \rfloor\)次修改,使A和B中所有非雷格子上的数字之和相等,输出修改之后的B。
题目分析:
首先考虑到,如果A和B的差异的格子不多于一半,可以把B直接修改为A,这时候A和B的数字和一定是相等的。
接下来注意到最大修改次数\(\left \lfloor \frac{nm}{2} \right \rfloor\)的限制。如果B和A的差异的格子多于一半,也就是B有一半以上的格子与A不同,构造一个A处处不同的图C,B一定与C差异的格子不多于一半。也就是说,B一定可以在规定次数内修改成为C。
容易得出,A和C的数字和是相等的。这里借助之前某道扫雷构造题的思路,如果图X的数字和记为x,它表示图X中一共有x个(雷,非雷)或(非雷,雷)的相邻二元对,仅考虑数字和时,在数学形式上雷与非雷的情况是完全等价的,因此图A和与它处处不同的图C拥有相同的数字和。
那么我们可以得出本题的解法:如果B和A差异的格子少于一半,把B修改成A;否则,把B修改成C,C是与A处处不同的图。
代码实现:
#include <bits/stdc++.h> using namespace std; const int maxn=1050; int n,m; char ma1[maxn][maxn]; char ma2[maxn][maxn]; char mb[maxn][maxn]; int cnt; int main(){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++){ scanf("%s",ma1[i]); } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(ma1[i][j]=='X')ma2[i][j]='.'; if(ma1[i][j]=='.')ma2[i][j]='X'; } } //for(int i=0;i<n;i++)ma2[i][m]='\0'; //for(int i=0;i<n;i++){ //printf("*%s\n",ma2); //} for(int i=0;i<n;i++){ scanf("%s",mb[i]); } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(ma1[i][j]==mb[i][j])cnt++; } } if(cnt<=(n * m / 2)){ for(int i=0;i<n;i++){ printf("%s\n",ma2[i]); } }else{ for(int i=0;i<n;i++){ printf("%s\n",ma1[i]); } } return 0; }
碎碎念:
扫雷的问题最大的特点是它只有雷、非雷(0和1)两种状态,而且在仅考虑数字和时,(1,0)和(0,1)又是在数学形式上全等价的,因此取反就是很常见的思路了。
这道题的入手点在于最大修改次数\(\left \lfloor \frac{nm}{2} \right \rfloor\)的限制。考虑过把B修改成A的情况,再去考虑B不能修改成A的情况时,就很自然地能想到把B修改成A全部取反的C了。
隐约记得上次做的某道扫雷题也是同样的思路,但我又突然记不得具体题目。

浙公网安备 33010602011771号