Codeforces-Round-#363- One Bomb

One Bomb

time limit per test1 second 
memory limit per test256 megabytes 
inputstandard input 
outputstandard output 
You are given a description of a depot. It is a rectangular checkered field of n × m size. Each cell in a field can be empty (“.”) or it can be occupied by a wall (“*”).

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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值