BZOJ4691 Let There Be Light

来源:互联网 发布:巨人网络纪学锋离职 编辑:程序博客网 时间:2024/05/17 23:11

我怎么感觉此题难点在于判断线段是否与圆的边有交……让我想起了冷冻波那题……

我们考虑状压DP,f[i][j]表示前i个气球,保证至少j集合内的光源能照到固定点,最少要拿掉多少个气球,然后每次进来一个气球,我们算他会挡住哪些光源的光,这样有了一个他会挡住的集合d,然后枚举状态j,如果j&d!=0,f[i][j]=f[i-1][j]+1,否则f[i][j]=f[i-1][j]

至于如何判线段与圆的边是否有交

首先要满足条件线段所在直线与圆心的距离小于等于圆的半径,这个我觉得用余弦定理算比较简单

其次还要满足两个端点不能都在园内,这个可以直接判

还要满足如果两个点都在圆外的话,那么过圆心做线段所在直线的垂线,垂线必须与线段有交

都在园外先判出来,然后我是连接两个端点和圆心构成一个三角形,如果两个端点所在的角有一个是钝角,那么就不能满足这个条件。判钝角可以用余弦定理然后判cos是否小于0

综上所述,余弦定理真是好东西-_-

最后把所有f值满足要求的状态算一下取个max即可

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<vector>#include<map>#include<set>#include<bitset>#include<queue>#include<stack>using namespace std;#define MAXN 2010#define MAXM 20#define MAXD 35010#define INF 1000000000#define MOD 1000000007#define eps 1e-8#define ll long longstruct pt{double x;double y;double z;};double sq(double x){return x*x;}double dis(pt x,pt y){return sqrt(sq(x.x-y.x)+sq(x.y-y.y)+sq(x.z-y.z));}double cal(pt A,pt B,pt O){double a=dis(A,O);double b=dis(A,B);double c=dis(B,O);double t=(sq(a)+sq(b)-sq(c))/(2*b);return sqrt(sq(a)-sq(t));}bool jud(pt A,pt B,pt O){double a=dis(A,B);double b=dis(A,O);double c=dis(B,O);return (sq(a)+sq(b)-sq(c))/(2*a*b)<0;}int n,m,lim;pt l[MAXM],p[MAXN];double v[MAXM],r[MAXN];int f[MAXD];pt ljss;int main(){int i,j;while(scanf("%d%d%d",&n,&m,&lim)){if(!n&&!m&&!lim){break;}memset(f,0,sizeof(f));for(i=1;i<=n;i++){scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z,&r[i]);}for(i=1;i<=m;i++){scanf("%lf%lf%lf%lf",&l[i].x,&l[i].y,&l[i].z,&v[i]);}scanf("%lf%lf%lf",&ljss.x,&ljss.y,&ljss.z);int N=1<<m;for(i=1;i<=n;i++){int d=0;for(j=1;j<=m;j++){if(cal(l[j],ljss,p[i])<=r[i]&&   !(dis(ljss,p[i])<=r[i]&&dis(l[j],p[i])<=r[i])&&   !((jud(ljss,l[j],p[i])||jud(l[j],ljss,p[i]))&&dis(ljss,p[i])>=r[i]&&dis(l[j],p[i])>=r[i])){d|=(1<<(j-1));}}for(j=0;j<N;j++){if(j&d){f[j]++;}}}double ans=0;for(i=0;i<N;i++){if(f[i]<=lim){double t=0;for(j=1;j<=m;j++){if(i&(1<<(j-1))){t+=v[j]/sq(dis(l[j],ljss));}}ans=max(ans,t);}}printf("%.6lf\n",ans);}return 0;}/*12 5 40 10 0 11 5 0 21 4 0 20 0 0 210 0 0 13 -1 0 25 -1 0 210 10 0 150 -10 0 110 -10 0 1-10 -10 0 110 10 0 10 10 0 24010 0 0 20010 -2 0 52-10 0 0 1001 1 0 20 0 012 5 40 10 0 11 5 0 21 4 0 20 0 0 210 0 0 13 -1 0 25 -1 0 210 10 0 150 -10 0 110 -10 0 1-10 -10 0 110 10 0 10 10 0 26010 0 0 20010 -2 0 52-10 0 0 1001 1 0 20 0 05 1 31 2 0 2-1 8 -1 8-2 -3 5 6-2 1 3 3-4 2 3 51 1 2 70 0 05 1 21 2 0 2-1 8 -1 8-2 -3 5 6-2 1 3 3-4 2 3 51 1 2 70 0 00 0 0 */


0 0