ZOJ——3871(Convex Hull)(计算几何+凸包问题)

Edward has n points on the plane. He picks a subset of points (at least three points), and defines the beauty of the subset as twice the area of corresponding convex hull. Edward wants to know summation of the beauty of all possible subsets of points (at least three points).

No two points coincide and no three points are on the same line.

Input

There are multiple test cases. The first line of input contains an integer Tindicating the number of test cases. For each test case:

The first line contains an integer n (3 ≤ n ≤ 1000). Each of following n lines contains 2 integers xi, yi which denotes a point (xi, yi) (0 ≤ |xi|, |yi| ≤ 109).

 

The sum of values n for all the test cases does not exceed 5000.

Output

For each case, if the answer is S, output a single integer denotes S modulo 998244353.

Sample Input

1
3
0 0
0 1
1 0

Sample Output

1

题意:给n个点,求在所有情况下的子集下(子集点数>=3),凸包的面积和的两倍。

题解:这题主要有几个方面,一个是凸包的面积,还有就是,在180度以内的点数。见代码。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int MAX = 1010;
const int mod = 998244353;
const double PI = acos(-1.0);
struct hh{
	int x,y;//这里用ll不对,我很迷
	double k;
}p[MAX],tp[MAX<<1];
int poww[MAX];
void init(){
	poww[0]=1;
	for(int i=1;i< MAX;++i){
		poww[i]=poww[i-1]*2%mod;//看有几个凸包
	}
}
bool cmp(hh a,hh b){
	return a.k<b.k;//角度从小到大
}
int area(hh a,hh b){
	return(((ll)a.x*b.y%mod-(ll)a.y*b.x%mod)%mod+mod)%mod;//叉乘求面积,因为是2倍和,所以不用除以二
}
int main(){
	init();
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		for (int i = 0; i < n;i++){
			scanf("%d%d",&p[i].x,&p[i].y);
		}
		int ans=0;
		for (int i = 0; i < n;i++){
			int cnt=0;
			for (int j = 0; j < n;j++){
				if(i==j) continue;
				tp[cnt]=p[j];
				tp[cnt++].k=atan2(p[j].y-p[i].y,p[j].x-p[i].x);
			}
			for(int j = 0;j < n;j++){
				tp[j+cnt]=tp[j];
				tp[j+cnt].k+=2.0*PI;//防止角度是负数
			}
			sort(tp,tp+cnt*2,cmp);//极角排序
			int r=0;
			for (int l = 0;l < cnt;l++){//排完用一半,很迷
				while(tp[r+1].k-tp[l].k<PI)r++;
				ans=(ans+(ll)area(p[i],tp[l])*((poww[r-l]-1+mod)%mod)%mod)%mod;//直接乘凸包数目不是很懂
			}
		}
		printf("%d\n",ans);//同结构体,直接用ll报错
	}
	return 0;
}

讲真,不是很好理解,多多学习呀! 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心脏dance

如果解决了您的疑惑,谢谢打赏呦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值