Mine Sweeper II
题意:
给你两个大小为 n * m 的扫雷图 A, B,要求通过最多 n * m/2 次转换(转换指 把一个不是雷的格子变成雷, 或者把一个是雷的格子变成空白格),使得 B图的值 和 A图的值相等(值 就是指 扫雷图上的所有数字之和,没有数字或者雷的地方的值为0)
1≤n,m≤1000
题解:
一开始做时毫无思路,如果暴力下手肯定不行,有什么优化的地方
又一次仔细看题后,突然想到为什么题目要求最多转换次数为n * m / 2,因为避免你将B全部都换一遍,而我们将A全部翻转的到A’,发现A’的值和A是一样的,而B在n * m / 2的交换次数下,是可以到A或者A’的,如果都不能到,那就输出-1,否则输出最近的一个
代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
const int maxn=1004;
char a[maxn][maxn],b[maxn][maxn];
char ia[maxn][maxn];
int main()
{int n,m;cin>>n>>m;char ch=getchar();for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>a[i][j];if(a[i][j]=='X')ia[i][j]='.';else if(a[i][j]=='.')ia[i][j]='X';}char ch=getchar();}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++)cin>>b[i][j];char ch=getchar();}int sum=0;int sum1=0;int ans=n*m/2;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(b[i][j]!=a[i][j])sum++;if(b[i][j]!=ia[i][j])sum1++;}}if(sum>ans&&sum1>ans){cout<<-1;return 0;}if(sum<=ans){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cout<<a[i][j];}cout<<endl;}}else if(sum1<=ans){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cout<<ia[i][j];}cout<<endl;}}return 0;
}