原题链接:Blocked Points
题目大意:题目中的 4-connected 给了一个递归定义:两个整数点距离为1,则这两个点是 4-connected 的;若两整数点a,b之间有一个整数点c,使得c与a、b都是4-connected的,那么a,b也是4-connected的。最后一段给出了问题:将距原点距离<=n的点分为一类,设为A,其他点分为一类,设为B;找出一个最小的点的集合,使得移除这些点就能使A、B之间没有 4-connected 的点对。例如,n=5时的情形如下,X表示要移除的点,x表示距离原点<=5的点:
5 . . . . . X . . . . .
4 . . X X X x X X X . .
3 . X x x x x x x x X .
2 . X x x x x x x x X .
1 . X x x x x x x x X .
0 X x x x x O x x x x X
-1 . X x x x x x x x X .
-2 . X x x x x x x x X .
-3 . X x x x x x x x X .
-4 . . X X X x X X X . .
-5 . . . . . X . . . . .
-5 -4 -3 -2 -1 0 1 2 3 4 5
大致思路:可以作一个半径为n的圆。距离原点距离为n的点,一部分在圆内或圆上,另一部分在圆外。四个象限情况相同,以第一象限为例,使用枚举的方法找出每个横坐标上方距离圆边界最近(在圆上或圆内)的点并移除,在这个点的纵坐标的基础上判断下一个横坐标上方有哪些点需要移除。另外有一种找规律的纯数学做法,附上链接,但是我觉得规律不是那么好找的,基本的方法还是要掌握好。
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
int main() {
long long n, count, pre, cur, i;
cin >> n;
if(n==0)
printf("1\n");
else {
count = 0;
pre = n;
cur = n;
for(i=1; i<=n; i++) {
cur = (long long)sqrt(n*n - i*i);
if(pre>cur) count += pre - cur;
else count++;
pre = cur;
}
cout<<4*count<<endl;
}
return 0;
}
由于输入可能很大,所以使用long long类型,同时求cur使用开根号的方法,而不是cur*cur + i*i > n*n的方法。