B. One Bomb
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.
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.
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.
3 4 .*.. .... .*..
YES 1 2
3 3 ..* .*. *..
NO
6 5 ..*.. ..*.. ***** ..*.. ..*.. ..*..
YES 3 3
这道题目,呃,还行吧,比较温柔,暴力就能过,但是看似简单,实际上写起来也容易乱,我自己就写得很乱,只能用注释来理清思路,别人的倒是一下子就出来了(羡慕.jpg)
代码如下(第二个(别人写的)的清楚度完爆第一个(我写的)直接看第二个就好):
#include<stdio.h>
#include<string.h>
#define max(a,b) a>b?a:b
int main()
{
int i,posi[1005],maxi,ki,marki[1005],j,posj[1005],maxj,kj,markj[1005];
int n,m,num,flag;
char s[1005][1005];
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(marki,0,sizeof(marki));
memset(markj,0,sizeof(markj));
for(i=0;i<n;i++)
scanf("%s",&s[i]);
num=0;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(s[i][j]=='*')
{
marki[i]++;
markj[j]++;
num++;
}
maxi=maxj=0;
ki=kj=0;
for(i=0;i<n;i++)//找出最多墙的行数的最大值
if(maxi<marki[i])
maxi=marki[i];
for(j=0;j<m;j++)//找出最多墙的列数的最大值
if(maxj<markj[j])
maxj=markj[j];
if(maxi+maxj==0)//如果根本就没有墙,直接输出返回,相当于任意一个地方放一个炸弹都能让所有墙炸没
{
puts("YES");
printf("1 1\n");
continue;
}
for(i=0;i<n;i++)//找出最多墙的行数,记录,如果有相同的也要记录,用数组有点晕,所以学习了别人下面有更简单的方法
if(maxi==marki[i])
posi[ki++]=i;
for(j=0;j<m;j++)//找出最多墙的列数来组合
if(maxj==markj[j])
posj[kj++]=j;
for(i=0,flag=1;i<ki&&flag;i++)
{
for(j=0;j<kj&&flag;j++)//将刚才找到的最大值进行组合,查看是否存在某个点满足条件,存在就返回
{
if(s[ posi[i] ][ posj[j] ] == '*')
{
if(marki[ posi[i] ] + markj[ posj[j] ] - 1 == num)//有两种情况,就是当前点是否有墙,有墙的话要 -1
{
puts("YES");
printf("%d %d\n",posi[i]+1,posj[j]+1);
flag=0;
}
}
else
{
if(marki[ posi[i] ] + markj[ posj[j] ] == num)
{
puts("YES");
printf("%d %d\n",posi[i]+1,posj[j]+1);
flag=0;
}
}
}
}
if(flag==1)
puts("NO");
}
}
求解时候更简单也更清晰的一种写法,还记得学长说,优美的代码能让我们更快的AC
#include<stdio.h>
#include<string.h>
#define max(a,b) a>b?a:b
int main()
{
int i,i_mark[1005],j,j_mark[1005];
int n,m,num,sw;
char G[1005][1005];
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(i_mark,0,sizeof(i_mark));
memset(j_mark,0,sizeof(j_mark));
for(i=0;i<n;i++)
scanf("%s",&G[i]);
num=0;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(G[i][j]=='*')
{
i_mark[i]++;
j_mark[j]++;
num++;
}
for(i=0,sw=1;i<n&&sw;i++)//这样暴力因为n,m最多是1000,时间复杂度也就一百万而已,一秒可以大概跑个1000万吧(看情况)
for(j=0;j<m&&sw;j++)
{
if(G[i][j]=='*'&&i_mark[i]+j_mark[j]-1==num)
{
puts("YES");
printf("%d %d\n",i+1,j+1);
sw=0;
}
else if(G[i][j]!='*'&&i_mark[i]+j_mark[j]==num)
{
puts("YES");
printf("%d %d\n",i+1,j+1);
sw=0;
}
}
if(sw)
puts("NO");
}
}