BZOJ 1822 计算几何+网络流+二分答案 解题报告
来源:互联网 发布:湖南棋牌app源码 编辑:程序博客网 时间:2024/05/29 11:08
1822: [JSOI2010]Frozen Nova 冷冻波
Description
WJJ喜欢“魔兽争霸”这个游戏。在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵。我们认为,巫妖和小精灵都可以看成是平面上的点。 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以瞬间杀灭一个小精灵。 在森林里有N个巫妖,每个巫妖释放Frozen Nova之后,都需要等待一段时间,才能再次施放。不同的巫妖有不同的等待时间和施法范围,但相同的是,每次施放都可以杀死一个小精灵。 现在巫妖的头目想知道,若从0时刻开始计算,至少需要花费多少时间,可以杀死所有的小精灵?
Input
输入文件第一行包含三个整数N、M、K(N,M,K<=200),分别代表巫妖的数量、小精灵的数量和树木的数量。 接下来N行,每行包含四个整数x, y, r, t,分别代表了每个巫妖的坐标、攻击范围和施法间隔(单位为秒)。 再接下来M行,每行两个整数x, y,分别代表了每个小精灵的坐标。 再接下来K行,每行三个整数x, y, r,分别代表了每个树木的坐标。 输入数据中所有坐标范围绝对值不超过10000,半径和施法间隔不超过20000。
Output
输出一行,为消灭所有小精灵的最短时间(以秒计算)。如果永远无法消灭所有的小精灵,则输出-1。
Sample Input
2 3 1
-100 0 100 3
100 0 100 5
-100 -10
100 10
110 11
5 5 10
Sample Output
5
Source
JSOI2010第二轮Contest1
【解题报告】
经典建图方式,二分答案,S到巫妖王的容量(总时间/冷却时间)改变。
对于判断树木是否与线段相交,分两种情况讨论:
1:圆心作线段的垂线垂足不在线段上
方法:直接比较圆心与线段两个端点距离的最小值是否小于半径
2:圆心作线段的垂线垂足在线段上
方法:算出垂线长度后比较
区分1、2两种情况用点积即可,相当于间接判断cos的值得正负
代码如下:
/************************************************************** Problem: 1822 User: onepointo Language: C++ Result: Accepted Time:220 ms Memory:2192 kb****************************************************************/#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<queue>using namespace std;#define N 10000#define inf 0x3f3f3f3fint n,m,k;int head[N],vis[N],cnt=0;int S,T,cur[N],mp[255][255],mark[255];struct Point {double x,y;};struct Lich {double x,y,r;int t;}li[255];struct Spirit {double x,y;}sp[255];struct Tree {double x,y,r;}tr[255];struct Edge {int to,nxt,w;}e[N<<3];void adde(int u,int v,int w){ e[++cnt].w=w;e[cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt; e[++cnt].w=0;e[cnt].to=u;e[cnt].nxt=head[v];head[v]=cnt;}double qdis(Lich a,Spirit b){ return sqrt(pow((a.x-b.x),2)+pow((a.y-b.y),2));}double dis(double a,double b,double c,double d){ return sqrt(pow((a-c),2)+pow((b-d),2));}double Cross(Point a,Point b,Point c){ double x1=b.x-a.x,y1=b.y-a.y; double x2=c.x-a.x,y2=c.y-a.y; return x1*y2-x2*y1;}double dot(Point a,Point b,Point c){ double x1=b.x-a.x,y1=b.y-a.y; double x2=c.x-a.x,y2=c.y-a.y; return x1*x2+y1*y2;}bool in_cir(Lich a,Spirit b,Tree c){ Point tmp1,tmp2,tmp3; tmp1=(Point){a.x,a.y}; tmp2=(Point){b.x,b.y}; tmp3=(Point){c.x,c.y}; if(dot(tmp3,tmp1,tmp2)>=0) return min(dis(a.x,a.y,c.x,c.y),dis(b.x,b.y,c.x,c.y))<=c.r; else return abs(Cross(tmp1,tmp3,tmp2))/qdis(a,b)<=c.r;}bool bfs(){ memset(vis,-1,sizeof(vis)); queue<int>q;q.push(S);vis[S]=0; while(!q.empty()) { int u=q.front();q.pop(); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if(vis[v]==-1&&e[i].w) vis[v]=vis[u]+1,q.push(v); } } return vis[T]!=-1;}int dfs(int x,int f){ if(!f||x==T) return f; int w,used=0; for(int i=cur[x];i;i=e[i].nxt) if(vis[e[i].to]==vis[x]+1) { w=f-used; w=dfs(e[i].to,min(w,e[i].w)); e[i].w-=w;e[i^1].w+=w; used+=w; if(e[i].w) cur[x]=i; if(used==f) return used; } if(!used) vis[x]=-1; return used;}int Dinic(){ int ret=0; while(bfs()) { for(int i=S;i<=T;++i) cur[i]=head[i]; ret+=dfs(S,inf); } return ret;}bool check(int x){ cnt=1; memset(head,0,sizeof(head)); for (int i=1;i<=n;++i) { int tmp=x/li[i].t+1; adde(S,i,tmp); } for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(mp[i][j]) adde(i,j+n,1); for(int i=1;i<=m;++i) adde(i+n,T,1); return Dinic()==m;}int main(){ scanf("%d%d%d",&n,&m,&k); S=0;T=n+m+1; for(int i=1;i<=n;++i) scanf("%lf%lf%lf%d",&li[i].x,&li[i].y,&li[i].r,&li[i].t); for(int i=1;i<=m;++i) scanf("%lf%lf",&sp[i].x,&sp[i].y); for(int i=1;i<=k;++i) scanf("%lf%lf%lf",&tr[i].x,&tr[i].y,&tr[i].r); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) { double dist=qdis(li[i],sp[j]); if(dist>li[i].r) continue; bool flag=1; for(int _k=1;_k<=k;++_k) if(in_cir(li[i],sp[j],tr[_k])) {flag=0;break;} if(flag) mp[i][j]=1,mark[j]=1; } for(int i=1;i<=m;++i) if(!mark[i]) {printf("-1\n");return 0;} int l=0,r=inf,ans=inf; while(l<=r) { int mid=(l+r)>>1; if(check(mid)) r=mid-1,ans=min(ans,mid); else l=mid+1; } printf("%d\n",ans==inf?-1:ans); return 0;}
- BZOJ 1822 计算几何+网络流+二分答案 解题报告
- BZOJ 4443(SCOI2015)网络流+二分答案 解题报告
- BZOJ 3993 [SDOI 2015] 网络流+二分答案 解题报告
- BZOJ 1052 二分答案 解题报告
- BZOJ 1913 计算几何+排列组合 解题报告
- BZOJ 1356 计算几何 解题报告
- BZOJ 1337 计算几何 解题报告
- SPOJ 287 网络流最大流+二分答案 解题报告
- 计算几何 [二分答案]
- POJ3525/LA3890 Most Distant Point from the Sea 解题报告【计算几何】【二分答案】【半平面交】
- BZOJ 4077 Wf2014 Messenger 二分答案+计算几何
- BZOJ 2792 [POI 2012] 二分答案 解题报告
- BZOJ 1502 计算几何+自适应Simpson积分 解题报告
- BZOJ 1007 几何 解题报告
- hdu5563解题报告(计算几何)
- UVA 11090 SPFA+二分答案 解题报告
- CodeVS 1183 SPFA+二分答案 解题报告
- BZOJ4952 [Wf 2017] 二分答案 解题报告
- Spring学习笔记(七)Spring对Dao的支持
- leetcode 383. Ransom Note
- 关于绑定IP地址与端口号的见解
- poj 1873The Fortified Forest (凸包 二进制枚举)
- 关于Oracle 数据库等待事件library cache: mutex X
- BZOJ 1822 计算几何+网络流+二分答案 解题报告
- CF423div2-C
- XML文件操作函数
- VC6 C++控制台程序如何判断用户输入的是什么数字[必须小于128]?
- import { Injectable } from '@angular/core'; import { Http, Headers, RequestOptions, Response } from
- synchronized和lock的区别
- 安卓动画之位移动画
- Android Wi-Fi 设置带宽代码流程
- 【安全牛学习笔记】漏洞挖掘