我怎么感觉此题难点在于判断线段是否与圆的边有交……让我想起了冷冻波那题……
我们考虑状压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 long
struct 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 4
0 10 0 1
1 5 0 2
1 4 0 2
0 0 0 2
10 0 0 1
3 -1 0 2
5 -1 0 2
10 10 0 15
0 -10 0 1
10 -10 0 1
-10 -10 0 1
10 10 0 1
0 10 0 240
10 0 0 200
10 -2 0 52
-10 0 0 100
1 1 0 2
0 0 0
12 5 4
0 10 0 1
1 5 0 2
1 4 0 2
0 0 0 2
10 0 0 1
3 -1 0 2
5 -1 0 2
10 10 0 15
0 -10 0 1
10 -10 0 1
-10 -10 0 1
10 10 0 1
0 10 0 260
10 0 0 200
10 -2 0 52
-10 0 0 100
1 1 0 2
0 0 0
5 1 3
1 2 0 2
-1 8 -1 8
-2 -3 5 6
-2 1 3 3
-4 2 3 5
1 1 2 7
0 0 0
5 1 2
1 2 0 2
-1 8 -1 8
-2 -3 5 6
-2 1 3 3
-4 2 3 5
1 1 2 7
0 0 0
0 0 0
*/