您的位置:首页 > 其它

Convex(扫描线降维)

2015-07-30 10:48 204 查看

Convex

Time Limit: 10000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1838 Accepted Submission(s): 552


[align=left]Problem Description[/align]
Your task is very simple. You will get the coordinates of n points in a plane. It is guaranteed that there are no three points on a straight line. You can choose any four points from these points to construct a quadrangle. Now, please tell me how many convex quadrangles you can construct.

[align=left]Input[/align]
The first line of input contain an integer z (z ≤ 20), indicating the number of test cases.
For each test case, the first line contain an integer n (4 ≤ n ≤ 700), indicating the number of points. Each of the next n lines contains two integers x and y (-1000000 ≤ x, y ≤ 1000000), indicating the coordinate of corresponding point.

[align=left]Output[/align]
For each test case, just output a single integer, the number of convex quadrangles you can construct.

[align=left]Sample Input[/align]

2
4
0 0
0 1
1 0
1 1
4
0 0
1 0
0 1
-1 -1

[align=left]Sample Output[/align]

1
0

题意:给出700个点,求可以构成多少个凸四边形,如果暴力的话肯定会超时
  那么可以逆向思维,C4n 个四边形减去凹四边形即可
  只要一个三角形中有一个点就是一个凹四边形,但是暴力找三角形照样会超时
  那么久找一个点在多少个三角形中和最后统计的每个三角形中的点数的总数是一样的
  要想找一个点在多少个三角形中就可以找一个点没在多少个三角形中然后C3n个总共的三角形减去这个值即可
  用扫描线法找到其不再多少个三角形的时候,只要枚举每个点,以这个点为中心点的话,和其他每个点连线,找这个线的一侧的点数j , 其上面任选两个点即可构成一个不包含它的三角形
所以就可以C2j 个三角形不包含它,所以先以中心点,将其他点按犄角排序,然后开始逆时针扫描另一侧不用扫描因为在线在转的时候回有扫到下侧的点的,要是考虑两侧的话所有的三角形会被算两遍,这样 枚举中心点是n 的复杂度,每次排序是logn 统计数目又是找点又是n 的,所以最后的复杂度就是n*(logn+n) 这样就不会超时了,起到了降维的作用
  下面是代码:

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

#define eps 1e-8
#define pi acos(-1.0)
#define N 750

int n;

struct point
{
double x, y;
point(){}
point(double _x, double _y ):x(_x), y(_y){}
};

point P
;
double ang[2*N];
int main()
{
//printf("%d", 700*699*698/6);
int T, n;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf("%lf %lf", &P[i].x, &P[i].y);

long long ans = (long long)n*(n-1)*(n-2)*(n-3)/24;//C(n,4)
for(int i = 0; i < n; i++)
{
long long cnt = (long long)(n-1)*(n-2)*(n-3)/6;//cnt记录包含i的三角形个数

int c = 0;
for(int j = 0; j < n; j++)
{
if(i == j) continue;
ang[c++] = atan2(P[j].y-P[i].y, P[j].x - P[i].x);
}

sort(ang, ang+c);
for(int j = c; j < 2*c; j++)
{
ang[j] = ang[j-c] + 2*pi;
//     printf("a--   %lf\n", ang[j-c] * 180.0 /pi);
}
// puts("");

int k = 1;

//puts("haha");while(t < 1000000000) t++;
for(int j = 0; j < c; j++)//不包含i的三角形
{
while(ang[k] - ang[j] < pi) k++;
int d = k-j-1;
//   printf("d = %d\n", d);
if(d > 1) cnt -= d*(d-1)/2;
}

ans -= cnt;
}
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: