HDU 4978 A simple probability problem.(概率模型+凸包周长)
题意:一个直径为d的圆中有n个点,每两点间有线段连接,一个平面上有间距都为d的平行线,求将原放在该平面上至少有一条线段与平行线相交的概率;
思路:
蒲丰针问题;http://wenku.baidu.com/link?url=s3rJRGUhCZ7kmsXA6o7Edr8h1rJJbibu2Ocs1Yf5BpsPwSkjkK9w-uVSV4d-cBGV36UA9bpxVfqLLA9qlPwbWkYbjkFzDaP_N5dtWHVT_mi
长度为L的针与间距为d的平行线相交的概率为P=2*L/(pi*d);
凸N边形与间距为d的平行线相交的概率为P=C/(pi*d);(C为凸N边形周长);
本题需要求的即凸包周长,结果为周长除以(π乘以直径);
样例跑出来不一样,几何题就是这么神奇。。。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const double epsi=1e-10; const double pi=acos(-1.0); const int maxn=10005; struct point{ double x,y; point(){} point(double xx,double yy):x(xx),y(yy){} point operator -(const point &op2)const{ return point(x-op2.x,y-op2.y); } double operator ^(const point &op2) const{ //两个点向量的叉积 return x*op2.y-y*op2.x; } }; inline int sign(const double &x){ if(x>epsi) return 1; if(x<-epsi) return -1; return 0; } inline double sqr(const double &x){ return x*x; } inline double mul(const point &p0,const point &p1,const point &p2){ return (p1-p0)^(p2-p0); } inline double dis2(const point &p0,const point &p1){ return sqr(p0.x-p1.x)+sqr(p0.y-p1.y); } inline double dis(const point &p0,const point &p1){ return sqrt(dis2(p0,p1)); } int n,l; //n个顶点,最近距离为l point p[maxn],convex_hull; //多边形顶点序列为p[],最低位置的点为convex_hull inline bool cmp(const point &a,const point &b){ //相对最低点,各点极角从小到大,距离从近到远排序 return sign(mul(convex_hull,a,b))>0||sign(mul(convex_hull,a,b))==0&&dis2(convex_hull,a)<dis2(convex_hull,b); } int convex(point *a,int n,point *b){ //计算含n个点的点集a的凸包b if(n<3) printf("Wrong in Line %d\n",__LINE__); //顶点数小于3,输出失败信息 for(int i=1;i<n;i++) //计算最低点convex_hull if(sign(a[i].x-a[0].x)<0||sign(a[i].x-a[0].x)==0&&sign(a[i].y-a[0].y)<0) swap(a[0],a[i]); convex_hull=a[0]; sort(a,a+n,cmp); //按极角和距离排序 int newn=2; b[0]=a[0];b[1]=a[1]; //a[0],a[1]入栈 for(int i=2;i<n;i++){ while(newn>1&&sign(mul(b[newn-1],b[newn-2],a[i]))>=0) --newn; //弹出栈顶所有未左转指向扫描顶点i的元素 b[newn++]=a[i]; //顶点i入栈 } return newn; //栈顶指针 } int main(){ int t,cas; scanf("%d",&t); for(cas=1;cas<=t;cas++) { scanf("%d%d",&n,&l); for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); printf("Case #%d: ",cas); if(n>2) { n=convex(p,n,p); p[n]=p[0]; //首尾相连 double ans=0; for(int i=0;i<n;i++) ans+=dis(p[i],p[i+1]); //累计凸包边长 //ans+=2*pi*l; printf("%.4lf\n",ans/(pi*l)); } else if(n==2) { double ans=dis(p[0],p[1]); printf("%.4lf\n",2*ans/(pi*l)); } else printf("0.0000\n"); } return 0; }
有些梦想现在不去实现,以后就再也没机会了!!