One Bomb
You have one bomb. If you lay the bomb at the cell (x, y), then after triggering it will wipe out all walls in the row x and all walls in the column y.
You are to determine if it is possible to wipe out all walls in the depot by placing and triggering exactly one bomb. The bomb can be laid both in an empty cell or in a cell occupied by a wall.
Input
The first line contains two positive integers n and m (1 ≤ n, m ≤ 1000) — the number of rows and columns in the depot field.
The next n lines contain m symbols “.” and “” each — the description of the field. j-th symbol in i-th of them stands for cell (i, j). If the symbol is equal to “.”, then the corresponding cell is empty, otherwise it equals “” and the corresponding cell is occupied by a wall.
Output
If it is impossible to wipe out all walls by placing and triggering exactly one bomb, then print “NO” in the first line (without quotes).
Otherwise print “YES” (without quotes) in the first line and two integers in the second line — the coordinates of the cell at which the bomb should be laid. If there are multiple answers, print any of them.
Examples
input
3 4
.*..
….
.*..
output
YES
1 2
input
3 3
..*
.*.
*..
Output
NO
input
6 5
..*..
..*..
..*..
..*..
..*..
Output
YES
3 3
给定一个n * m 的矩形,'.'代表空地,'*'代表障碍,在(x,y)处的一个炸弹能把x行,y列所有障碍变成空地,即'*'变'.',问矩形区域内能否放一个炸弹使矩形内所有障碍都被清除(炸弹也能放在空地上,也能放在障碍上)。
题目链接:One Bomb
解题思路:
考虑一般情况,符合条件的炸弹(x,y),x上的障碍总数(mpx[x])+y上的障碍总数(mpy[y]) = 总障碍数(cnt),但如果(x,y)处就是障碍的话,就要把cnt + 1,才满足等式。
因此用mpx[x],mpy[y] 处理上述条件的数目,然后直接循环打擂,求出最大的mpx[x],mpy[y]即可。
但会发现,在打擂遇到相同的时候,比如说
10 20
....................
.........*..........
....................
....................
....................
....................
....................
....................
...*..............*.
....................
不难发现,如果仅仅按照上述思路编程,得出的坐标应该是 (4,9) ,然而答案应该是(10,9);
考虑相同的情况,如果此时打擂遇到的 行数(列数) 与 已经选好的 列数(行数) 组合成的坐标是障碍的话,那么等于
代码:
#include<cstdio>
#include<iostream>
#include<map>
using namespace std;
const int N = 1e3 +5;
char a[N][N];
int n,m;
map<int,int> mpx;
map<int,int> mpy;
int main()
{
int i,j,x,y,cnt,mx,px,py;
while(~scanf("%d%d",&n,&m)){
for(i = 0;i < n;i++){
scanf("%s",a[i]);
}
cnt = 0;
mpx.clear(),mpy.clear();
for(i = 0;i < n;i++){
for(j = 0;j < m;j++){
if(a[i][j] == '*') {
cnt ++; //记录障碍个数
mpx[j] ++; //记录在j列的炸弹个数
mpy[i] ++; //记录在i行的炸弹个数
}
}
}
x = y = 99999; //矩形最大为1000 * 1000,所以99999为无效数据
mx = 0;
map<int,int> :: iterator it = mpx.begin();
for(mx = 0; it != mpx.end();it++){ //找到x列最多障碍的列数
if(mx < it->second) {
mx = it->second;
x = it -> first;
}
}
it = mpy.begin();
for(mx = 0; it != mpy.end();it++){
if(mx < it->second) { //找到y行最多障碍的行数
mx = it->second;
y = it -> first;
}
else if(mx == it -> second && a[it -> first][x] != '*') {
mx = it->second; //注意当行数有相同障碍数时,如果不是在已选好的x那点的障碍,则更新
y = it -> first;
}
}
it = mpx.begin();
for(mx = mpx[x]; it != mpx.end();it++){
if(mx == it->second && a[y][it -> first] != '*') {
mx = it->second; //再一次尝试更新x,如果当列数有相同障碍时,并且不是在已选好的y那点的障碍,则更新
x = it -> first;
}
}
if(cnt <= 1) { //0或者1个障碍时
if(!cnt) x = y = 0; //0个障碍
printf("YES\n%d %d\n",y + 1,x + 1);
}
else if(cnt > 1){
if(x != 99999 && y != 99999 && a[y][x] == '*') cnt++; //如果选的y,x是同一个障碍的坐标,为了满足下面的等式,+1处理
if(x != 99999 && y != 99999 && mpy[y] + mpx[x] == cnt){ //保证这个炸弹能炸掉所有障碍
printf("YES\n%d %d\n",y+1,x+1);
}
else printf("NO\n");
}
}
return 0;
}