AtCoder Beginner Contest 191
Posted 佐鼬Jun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 191相关的知识,希望对你有一定的参考价值。
C - Digital Graffiti
题目链接: link.
题意:
在一个矩阵中 ‘ . ’ ‘.’ ‘.’代表空,#代表图案,现在矩阵中用#绘制了几个多边形,多边形之间没有相交,矩阵为 n ⋅ m n·m n⋅m的,现在矩阵的中多边形有多少个直边,直边说明没有断开,也没有突起和凹下。
思路:
我的思路是对于图形的上面下面左边右边都判断一下,即几个上面,几个下面,几个左面,几个右面。对于正面来说,就是没有断开,比较暴力的做法,但是很好理解
#include <bits/stdc++.h>
using namespace std;
const int N = 20;
int n, m;
char s[N][N];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%s", s[i] + 1);
}
int res = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (s[i][j] == '#' && s[i - 1][j] != '#') {
int k;
res++;
for (k = j + 1; k <= m; k++) {
//当前点是‘#’,且不是内部点,必须是最外部的点
if (s[i][k] == '#' && s[i - 1][k] != '#') {
continue;
} else
break;
}
j = k - 1;
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (s[i][j] == '#' && s[i + 1][j] != '#') {
res++;
int k;
for (k = j + 1; k <= m; k++) {
//最下面的‘#’点,且不是内部点
if (s[i][k] == '#' && s[i + 1][k] != '#') {
continue;
} else
break;
}
j = k - 1;
}
}
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s[j][i] == '#' && s[j][i - 1] != '#') {
res++;
int k;
for (k = j + 1; k <= n; k++) {
//最左边的‘#’号点
if (s[k][i] == '#' && s[k][i - 1] != '#') {
continue;
} else
break;
}
j = k - 1;
}
}
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s[j][i] == '#' && s[j][i + 1] != '#') {
res++;
int k;
for (k = j + 1; k <= n; k++) {
//最右边的‘#’点
if (s[k][i] == '#' && s[k][i + 1] != '#') {
continue;
} else
break;
}
j = k - 1;
}
}
}
cout << res << endl;
}
另一种思路:
借鉴网上其他大佬的思路,对于多边形是都是直边时,多边形的顶点数=边数,即多边形直角边的数量=边数,是个定理(规律),在此记个笔记。
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int n, m;
char s[N][N];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%s", s[i] + 1);
}
int res = 0;
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
int cnt = 0;
if (s[i][j] == '.') cnt++;
if (s[i][j + 1] == '.') cnt++;
if (s[i + 1][j] == '.') cnt++;
if (s[i + 1][j + 1] == '.') cnt++;
if (cnt == 1 || cnt == 3) res++;
}
}
cout << res << endl;
return 0;
}
D - Circle Lattice Points
题目链接: link.
题意:
给一个圆的圆心坐标 ( x , y ) (x,y) (x,y),半径 R R R,现在问你有多少个整数点(坐标的值都是整数值)坐落在圆内或圆上
思路:
坐标的范围给的是
1
0
5
10^5
105肯定不能两重循环枚举每个整数点都判断一遍,跑不了
O
(
n
2
)
O(n^2)
O(n2),需要只跑一遍循化,那么就可以只枚
x
x
x的值,然后求出
y
y
y的范围在范围之内的个数好算,直接
∣
u
p
−
d
o
w
n
+
1
∣
|up-down+1|
∣up−down+1∣,操作起来就是枚举
x
x
x的值,从
x
−
r
x-r
x−r枚举到
x
+
r
x+r
x+r,此时知道了圆心
(
x
,
y
)
(x,y)
(x,y),也知道了枚举的一个点的位置
(
x
i
,
y
i
)
(x_i,y_i)
(xi,yi),那么此时这个点的上边界和下边界根据勾股定理来求,拿上边界距离,就是
y
i
+
R
2
−
(
x
−
x
i
)
2
y_i+\\sqrt{R^2 - (x-x_i)^2}
yi+R2−(x−xi)2就是上边界的值,下边界同理,所以这个
x
i
x_i
xi值下,也就是确定一个竖轴,确定出上下边界,那么上面的点数就是
∣
u
p
−
d
o
w
n
+
1
∣
|up-down+1|
∣up−down+1∣
注意: 这个题比较卡精度,所以我开了
l
o
n
g
d
o
u
b
l
e
long double
longdouble,且半径
R
R
R还加了一个偏移量eps,这个题对于取整问题,可以直接用函数
f
l
o
o
r
floor
floor向上取整和
c
e
i
l
ceil
ceil向下取整
#include <bits/stdc++.h>
using namespace std;
#define eps 1e-14
#define ll long long
int main() {
long double x, y, r;
cin >> x >> y >> r;
r += eps;
ll res = 0;
for (int i = ceil(x - r); i <= floor(x + r); i++) {
long double up, down;
up = y + sqrt(r * r - (x - i) * (x - i));
down = y - sqrt(r * r - (x - i) * (x - i));
res += floor(up) - ceil(down) + 1;
}
cout << res << endl;
}
E - Come Back Quickly
题目链接: link.
题意:
给 n n n个点 m m m条边的单向图, a i a_i ai b i b_i bi c i c_i ci代表 a a a到 b b b的边权为 c c c,现在让你输出从每个点出发,又回到自己的最短路的距离(必须要走),如果走不了,那就输出-1
思路:
这个题给的点数和边数并不多,可以对每个点都跑一遍
D
i
j
k
s
t
r
a
Dijkstra
Dijkstra来求从每个点开始到其他点的最短路,然后再求最短环即可,也就是
r
e
s
=
m
i
n
(
r
e
s
,
f
(
i
,
j
)
+
f
(
j
,
i
)
)
res=min(res,f(i,j)+f(j,i))
res=min(res,f(i,j)+f(j,i)),但这个题有一个细节很恶心,通常我们默认点从自己到自己的最短路一般是0,但是这个题的边可以是自己连接自己,也就是说这里的自环边是要考虑进来的,与平常的最短路不一样。
所以要开个数组,
C
i
r
c
l
e
[
i
]
Circle[i]
Circle[i]存的是从
i
i
i的自环边的最短边
#include <bits/stdc++.h>
using namespace std;
const int N = 2020, M = 4040;
#define inf 0x3f3f3f3f
typedef pair<int, int> PII;
bool vis[N];
int h[N], e[M], ne[M], w[M], idx;
int dis[N], Circle[N];
int f[N][N];
int n, m;
void add(int a, int b, int c) {
e[idx] 以上是关于AtCoder Beginner Contest 191的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解