CF1182B Plus from Picture 题解
写在前面
为什么在已经有 \(12\) 篇题解后,我还是要写这篇题解?
因为这篇题解提供一个码量较小,且时间复杂度严格 \(O(wh)\) 的做法,目前这种做法题解区没有。
进入正题
设 \(cnt[i]\) 表示地图中的 * 周围四联通有 \(i\) 个 * 的位置的数量
考虑到地图中有且仅有一个 + 形图形的性质:
\(1\) :若要保证有且仅有一个 + 形图形,则 \(cnt[4]=1\) 。因为每个 + 形图形对应一个周围四联通有四个 * 的 * (中间那一个),所以周围四联通有四个 * 的 * 有且仅有一个 。
括号圈起来的是这一条所描述的点,后面也是如此:
*
*(*)*
*
\(2\) :若要保证有且仅有一个 + 形图形,则 \(cnt[1]=4\) 。因为每个 + 形图形对应四个周围四联通有一个 * 的 * ( + 形图形的最外围),所以周围四联通有一个 * 的 * 有且仅有四个 。
(*)
(*)*(*)
(*)
\(3\) :若要保证除 + 形图形各点之外,整张地图均为 . ,则 \(cnt[0]=0\) 且 \(cnt[3]=0\) 。因为 + 形图形中不存在这样的点,若存在,则必然是 + 形图形各点之外的 * ,不能保证除 + 形图形各点之外,整张地图均为 . 。
. . . .(*)
. * . . .
*(*). . .
. * . . .
\(4\) :对于 \(cnt[2]\) ,如果上面的点与下面的点,左边的点和右边的点分别相同,则这个点对结果无影响。因为 + 形图形可能存在这样的点。
*
**(*)*
(*)
*
\(5\) :对于 \(cnt[2]\) ,如果不满足上面情况,则地图中除 + 形图形各点之外,整张地图必然不均为 . 。因为 + 形图形中同样不存在这样的点。
. . . .
.(*)* .
. *(*).
. . . .
所以,只要判断这五条性质,就能得出结果。
复杂度分析
很显然,扫一遍数组就可以得到结论了。
时间复杂度: \(O(wh)\)
空间复杂度: \(O(wh)\)
完整代码
#include <bits/stdc++.h>
using namespace std;
int w,h,cnt[5];
char map1[501][501];
int main()
{
scanf("%d%d",&w,&h);
for(int i=0;i<w;i++)
scanf("%s",map1[i]);
for(int i=0;i<w;i++)
for(int j=0;j<h;j++)
{
int ans1=0,ans2=0;
if(map1[i][j]!='*')continue; \\如果不是*,没有必要计算
if(i-1>=0&&map1[i-1][j]=='*')ans1++;
if(i+1<w&&map1[i+1][j]=='*')ans1++; \\上下点的情况
if(j-1>=0&&map1[i][j-1]=='*')ans2++;
if(j+1<h&&map1[i][j+1]=='*')ans2++; \\左右点的情况
if(ans1%2&&ans2%2) \\判断上下左右点是否分别相等
{ \\如果分别相等则对应的计数一定都为偶数
printf("NO\n");
return 0;
}
cnt[ans1+ans2]++;
}
if(cnt[0]==0&&cnt[1]==4&&cnt[3]==0&&cnt[4]==1)printf("YES\n"); \\综合五条性质判断
else printf("NO\n");
return 0;
}
后记
于 \(2022\) 年 \(12\) 月 \(16\) 日达成最优解。


浙公网安备 33010602011771号