P4048 [JSOI2010]冷冻波
因为我数学太差,实在不会点到直线距离公式,只好叉积计算面积除以底来计算高了……
简单来说就是两个向量\((x1,y1),(x2,y2)\)的叉积为\((x1y2-x2y1)\),三角形ABC的向量\(AB\)和\(AC\)的叉积的绝对值就是这个三角形面积的两倍
这样的话枚举巫妖和精灵,然后看是不是有哪个圆的圆心到这条线的距离小于等于它的半径,是的话就有交点,gg了
然后就是二分+网络流乱搞喽……每只巫妖向能打到的精灵连边,二分时间,然后从源点向巫妖连边,记得注意\(0\)秒的时候也可以发射就是了,所以每只巫妖能发射的总次数是总时间除以冷却再加一
顺便一提我这个代码有点bug,因为有可能直线与圆相切,但切点不在线段上,这样的话巫妖能打到精灵,但按照上面的方法判断算是不行……所以我就改了改变成小于才不行然后A了……严格来说的话应该是用叉积判一下圆心到巫妖和精灵的两条线是否都在它与切点连线的同一侧的……实在懒了不想打……
//minamoto
#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=head[u],v=ver[i];i;i=Next[i],v=ver[i])
#define inf 0x3f3f3f3f
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
int read(){
int res,f=1;char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=1005,M=5e5+5;
int head[N],Next[M],ver[M],edge[M],tot=1;
void add(int u,int v,int e){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=0;
}
int dep[N],cur[N],q[N],S,T;
bool bfs(){
int h=1,t=0;
fp(i,S,T)cur[i]=head[i],dep[i]=-1;
q[++t]=S,dep[S]=0;
while(h<=t){
int u=q[h++];
go(u)if(dep[v]<0&&edge[i]){
dep[v]=dep[u]+1,q[++t]=v;
if(v==T)return true;
}
}return false;
}
int dfs(int u,int lim){
if(u==T||!lim)return lim;
int flow=0,f;
for(int &i=cur[u];i;i=Next[i]){
int v=ver[i];
if(dep[v]==dep[u]+1&&(f=dfs(v,min(lim,edge[i])))){
flow+=f,lim-=f;
edge[i]-=f,edge[i^1]+=f;
if(!lim)break;
}
}return flow;
}
int dinic(){int flow=0;while(bfs())flow+=dfs(S,inf);return flow;}
struct node{int x,y,r,t;}p[N];
int x[N],y[N],xx[N],yy[N],rr[N],vis[N],hh[N],n,m,k;
inline double pow(double x){return x*x;}
inline double dis(int i,int j){return sqrt(pow(p[i].x-x[j])+pow(p[i].y-y[j]));}
bool check(int i,int j,int k){
double cr=fabs((xx[k]-p[i].x)*(y[j]-p[i].y)-(x[j]-p[i].x)*(yy[k]-p[i].y));
cr/=dis(i,j);return cr>=rr[k];
}
int res,l,r,mid,ans;
bool ok(int mid){
tot=res;for(register int i=2;i<=tot;i+=2)edge[i]+=edge[i^1],edge[i^1]=0;
fp(i,S,T)head[i]=hh[i];
fp(i,1,n)add(S,i,mid/p[i].t+1);
return dinic()>=m;
}
int main(){
// freopen("frozen.in","r",stdin);
// freopen("frozen.out","w",stdout);
n=read(),m=read(),k=read(),S=0,T=n+1+m;
fp(i,1,n)p[i].x=read(),p[i].y=read(),p[i].r=read(),p[i].t=read();
fp(i,1,m)x[i]=read(),y[i]=read();
fp(i,1,k)xx[i]=read(),yy[i]=read(),rr[i]=read();
fp(i,1,n)fp(j,1,m)if(dis(i,j)<=p[i].r){
int flag=1;
fp(l,1,k)if(!check(i,j,l)){flag=0;break;}
if(flag)add(i,j+n,1),vis[j]=1;
}fp(i,1,m)if(!vis[i])return puts("-1"),0;
fp(i,1,m)add(i+n,T,1);
fp(i,S,T)hh[i]=head[i];
res=tot,l=0,r=4000000,mid,ans;
while(l<=r){
mid=(l+r)>>1;
ok(mid)?(ans=mid,r=mid-1):(l=mid+1);
}printf("%d\n",ans);return 0;
}
深深地明白自己的弱小