TC SRM 655 Div1 Level 3 题解

TC SRM 655 Div1 Level 3 题解

题目传送门

dp+几何

首先可以发现凸包是顺时针排列的一些线段构成的。我们可以预处理每一个蓝点是否都在一个线段\(r[i]\rightarrow r[j]\),(箭头表示在凸包上的方向)的内测。

然后蓝点就没有用了。

然后再回想一下凸包的定义:所有点连接起来都是外凸的,且可以框住所有的点。

然后我们像构建凸包那样来dp。

首先钦定最下面,最靠左的点。然后将其它的极交排序。\(dp_{i,j}\)表示当前凸包上的线段为\(r[i]->r[j]\)的概率。

注意:需要判断凸包的凸性!

/*
{
######################
#       Author       #
#        Gary        #
#        2021        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
struct vec{
	int x,y;
	vec (mp A){
		x=A.FIR;
		y=A.SEC;
	}
	vec (int A,int B){
		x=A,y=B;
	}
	vec (){
		
	}
	bool operator * (vec oth){//返回叉乘结果是否>=0 
		return 1ll*x*oth.y>=1ll*y*oth.x;
	}
	vec operator - (vec oth){
		return vec (x-oth.x,y-oth.y);
	}
	vec operator + (vec oth){
		return vec(x+oth.x,y+oth.y);
	}
};
bool cmp(vec A,vec B){
	if(A.y!=B.y){
		return A.y<B.y;
	}
	return A.x<B.x;
}
bool cmp_angle(vec A,vec B){//极角排序 
	return (B-A)*(vec(0,0)-A); 
}
bool ok[120][120];
bool ok2[120][120];
double pro[120][120];
double dp[120][120];
map<mp,int> id;
class BichromeSky{
	public:
	double totallyCovered(vector<int> rx,vector<int> ry,vector<int> P,vector<int> bx,vector<int> by){
		vector<vec> r,b;
		int n=rx.size();
		vector<double> p(n);
		rep(i,n){
			p[i]=P[i]/1000.0;
		}
		rep(i,n){
			r.PB(vec(II(rx[i],ry[i])));
			id[II(rx[i],ry[i])]=i;
		}
		rep(i,bx.size())
			b.PB(vec(II(bx[i],by[i])));
		sort(ALL(r),cmp);
		sort(ALL(b),cmp);
		rep(i,n) rep(j,n){
			if(j==i) continue;
			int idi,idj;
			idi=id[II(r[i].x,r[i].y)];
			idj=id[II(r[j].x,r[j].y)];
			ok[idi][idj]=true;
			rep(k,b.size()){
				ok[idi][idj]&=(r[i]-b[k])*(r[j]-b[k]);
			}
		}
		double rest=0;
		double pp=1.0;
		rep(i,n){
			if(n-i<2) break;
			deque<vec> oth;
			for(int j=i+1;j<n;++j) oth.PB(r[j]-r[i]);
			sort(ALL(oth),cmp_angle);
			oth.push_front(vec(II(0,0)));
			oth.PB(vec(II(0,0)));
			int sz=oth.size();
			vector<double> thisp(sz);
			rep(j,sz){
				vec now=oth[j]+r[i];
				int idd=id[II(now.x,now.y)];
				thisp[j]=p[idd];
			}
			rep(j,sz)
				for(int k=j+1;k<sz;++k){
					dp[j][k]=0.0;
					pro[j][k]=1.0;
					int idj,idk;
					vec jv,kv;
					jv=oth[j]+r[i];
					kv=oth[k]+r[i];
					idj=id[II(jv.x,jv.y)];
					idk=id[II(kv.x,kv.y)];
					ok2[j][k]=ok[idj][idk];
					for(int l=j+1;l<k;++l){
						if(!((oth[j]-oth[l])*(oth[k]-oth[l]))){
							pro[j][k]*=1.0-thisp[l];		
						}
					}
				}
			double tmp=0.0;
			for(int j=1;j+1<sz;++j){
				if(ok2[0][j])
					dp[0][j]=thisp[j]*pro[0][j];	
			}
			rep(j,sz)
				for(int k=j+1;k<sz;++k){
					for(int l=k+1;l<sz;++l){
						if(ok2[k][l]&&(oth[l]-oth[k])*(oth[j]-oth[k])){							
							dp[k][l]+=dp[j][k]*thisp[l]*pro[k][l]; 
						} 
					}
				}
			rep(j,sz){
				if(ok2[j][sz-1])
			    	tmp+=dp[j][sz-1];
			}
			tmp*=pp;
			rest+=tmp;
			pp*=(1.0-thisp[0]);
		}
		return rest;
	}
};
posted @ 2021-01-03 10:29  WWW~~~  阅读(99)  评论(0)    收藏  举报