还是me太弱了,各种细节疏忽,把一个double数组用int comp(const int &a,const int &b)排序。导致double四舍五入为int,手动断点输出查错,查了一下午·····
还好codevs上会给错误点,不然me还查不出来这个错····
真的有毒性!!
输入第一行包含一个正整数 n, 表示房子的总数。接下来有 n 行,分别表示 每一个房子的位置。对于 i = 1, 2, .., n, 第i 个房子的坐标用一对整数 xi和yi来表 示,中间用空格隔开。
输出文件包含一个实数,表示平均有多少个房子被信号所覆盖,需保证输出 结果与精确值的绝对误差不超过0.01。
Sample Input
4
0 2
4 4
0 0
2 0
Sample Output
3.500
3.5, 3.50, 3.500, … 中的任何一个输出均为正确。此外,3.49, 3.51,
3.499999,…等也都是可被接受的输出。
100%的数据保证,对于 i = 1, 2, .., n, 第 i 个房子的坐标(xi, yi)为整数且
–1,000,000 ≤ xi, yi ≤ 1,000,000. 任何三个房子不在同一条直线上,任何四个房子不
在同一个圆上;
40%的数据,n ≤ 100;
70%的数据,n ≤ 500;
100%的数据,3 ≤ n ≤ 1,500。
BZOJ 1692ms
#include
#include
#include
#include
using namespace std;
const double Pi=3.1415926535898;
const double dPi=Pi*2;
int n;
double t[3005];
struct Point{
int x,y;
}p[1501];
long long is_concave=0;
int comp(const double &a,const double &b){
return along long C(int N,int M){
long long rt=1;
for(int i=0;i1);
return rt;
}
void calcu(int u){
double angle;
for(int i=1;i<=n;i++){
if(u==i) {t[i]=-123456789.0;continue;}
complex<double> poi(p[i].x-p[u].x,p[i].y-p[u].y);
t[i]=arg(poi);
}
}
void solve(){
int p,dn=n*2;
long long isnot_covered;
for(int i=1;i<=n;i++){
p=2;isnot_covered=0;
calcu(i);
sort(t+1,t+n+1,comp);
for(int j=n+2;j<=dn;j++)
t[j-1]=t[j-n]+dPi;
for(int j=2;j<=n;j++){
p=max(p,j+1);
while(p<=dn-1&&t[p]if(p-j>=2) isnot_covered+=C(p-j,2);
}
is_concave+=C(n-1,3)-isnot_covered;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
solve();
printf("%lf",3.0+((C(n,4)-is_concave)*2.0+is_concave*1.0)/C(n,3));
}
很容易可以想到大暴力算法:
对于每个圆,枚举剩下的点,判断是否在圆内。
但是,会超时。
手推几组只有四个点的数据,发现一共有两种情况:
1.四个点构成凸四边形时,可以找到两个圆覆盖剩下的点
2.四个点构成凹四边形时,可以找到一个圆覆盖剩下的点
这时候就可以简化问题。求出凸四边形和凹四边形的个数,答案即为
[(凸四边形数*2)+(凹四边形数*1)+(总四边形数*3)]/总四边形数。
因为三点才确定一个圆,因此总四边形数*3
对于一个四边形,一个顶点在另外三个顶点的构成的三角形内,我们称这个四边形是一个凸四边形。
我们需要判断一个点是否在三角形内,来确定这是个什么四边形,运用补集转化的思想,求出一个点不被三角形包含的个数,用总数去减,剩下的就是包含的。
求不包含的比较简单,但是细节多,枚举每个点作为坐标原点,对剩下的点使用极角排序
(这个就自己去查啦,me是用的complex库里自带的复数弧度角,也可以用atan2去算)
排好序后,用Θ(n)的复杂度逆时针for一遍
(想一想,过当前坐标原点作两根射线,这两根射线将平面分为两部分,其中一部分夹角<=180°。如果某个三角形三个顶点都在这个部分,那么这个三角形就不会包含当前坐标原点,正确性显然。for的过程只需要将这两根射线转一圈就好。正是为了不重不漏,我们使用极角排序,让这些点沿着顺时针有序)
算出所有不包含当前点的三角形数。再加上前面所说,这道题就写完了~
可以去看一看这一篇博客,有图好理解些。
http://blog.csdn.net/qpswwww/article/details/45334033
附