hdu3622 二分+2sat
题意:
给你N组炸弹,每组2个,让你在这N组里面选取N个放置,要求(1)每组只能也必须选取一个(2)炸弹与炸弹之间的半径相等(3)不能相互炸到对方。求最大的可放置半径。
思路:
二分去枚举半径,然后用2sat去判断是否可行,在2sat里,每组炸弹的两个是正常对,任何两组的任何两个距离小于等于mid那么这两个是矛盾对。这样强连通缩短,然后判断有没有一组是在同一个强连通块里的,没有那么就ok继续更新二分查找答案。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stack> #define N_node 200 + 10
#define N_edge 100000 + 100
using namespace std; typedef struct
{
int to ,next;
}STAR; typedef struct
{
double x1 ,x2 ,y1 ,y2;
}NODE; STAR E1[N_edge] ,E2[N_edge];
NODE node[111];
int list1[N_node] ,list2[N_node] ,tot;
int Belong[N_node] ,cnt;
int mark[N_node];
stack<int>st; void add(int a , int b)
{
E1[++tot].to = b;
E1[tot].next = list1[a];
list1[a] = tot; E2[tot].to = a;
E2[tot].next = list2[b];
list2[b] = tot;
} void DFS1(int s)
{
mark[s] = 1;
for(int k = list1[s] ;k ;k = E1[k].next)
{
int xin = E1[k].to;
if(!mark[xin]) DFS1(xin);
}
st.push(s);
} void DFS2(int s)
{
mark[s] = 1;
Belong[s] = cnt;
for(int k = list2[s] ;k ;k = E2[k].next)
{
int xin = E2[k].to;
if(!mark[xin]) DFS2(xin);
}
} double diss(double x1 ,double y1 ,double x2 ,double y2)
{
double tmp = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
return sqrt(tmp);
} bool ok(double mid ,int n)
{
memset(list1 ,0 ,sizeof(list1));
memset(list2 ,0 ,sizeof(list2));
tot = 1;
for(int i = 0 ;i < n ;i ++)
for(int j = i + 1 ;j < n ;j ++)
{
int a ,b;
double dis = diss(node[i].x1 ,node[i].y1 ,node[j].x1 ,node[j].y1);
if(dis <= mid)
{
a = i * 2 ,b = j * 2;
add(a ,b^1) ,add(b ,a^1);
}
dis = diss(node[i].x1 ,node[i].y1 ,node[j].x2 ,node[j].y2);
if(dis <= mid)
{
a = i * 2 ,b = j * 2 + 1;
add(a ,b^1) ,add(b ,a^1);
}
dis = diss(node[i].x2 ,node[i].y2 ,node[j].x1 ,node[j].y1);
if(dis <= mid)
{
a = i * 2 + 1,b = j * 2;
add(a ,b^1) ,add(b ,a^1);
}
dis = diss(node[i].x2 ,node[i].y2 ,node[j].x2 ,node[j].y2);
if(dis <= mid)
{
a = i * 2 + 1,b = j * 2 + 1;
add(a ,b^1) ,add(b ,a^1);
}
}
memset(mark ,0 ,sizeof(mark));
while(!st.empty())st.pop();
for(int i = 0 ;i < n * 2 ;i ++)
if(!mark[i]) DFS1(i);
memset(mark ,0 ,sizeof(mark));
cnt = 0;
while(!st.empty())
{
int xin = st.top();
st.pop();
if(mark[xin]) continue;
++cnt;
DFS2(xin);
}
int mk = 0;
for(int i = 0 ;i < n * 2 ;i += 2)
{
if(Belong[i] == Belong[i^1])
mk = 1;
}
return !mk;
} int main ()
{
int n ,i;
while(~scanf("%d" ,&n))
{
for(i = 0 ;i < n ;i ++)
scanf("%lf %lf %lf %lf" ,&node[i].x1 ,&node[i].y1 ,&node[i].x2 ,&node[i].y2);
double low ,mid ,up ,ans = 0;
low = 0 ,up = 2000000000;
for(i = 1 ;i <= 100 ;i ++)
{
mid = (low + up) / 2;
if(ok(mid ,n))
ans = low = mid;
else up = mid;
}
printf("%.2lf\n" ,ans/2);
}
return 0;
}
hdu3622 二分+2sat的更多相关文章
- HDU3622(二分+2-SAT)
Bomb Game Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 3622 Bomb Game(二分+2SAT)
题意:有一个游戏,有n个回合,每回合可以在指定的2个区域之一放炸弹,炸弹范围是一个圈,要求每回合的炸弹范围没有重合.得分是炸弹半径最小的值.求可以得到的最大分数. 思路:二分+2SAT. 二分炸弹范围 ...
- hdu 3622 二分+2-sat
/* 二分+2-sat 题意:在一个二维平面上给你n个炸弹,和2*n个位置,每一行的两个位置只能有一个放炸弹 现在炸弹爆炸有一个半径,当炸弹爆炸时两个炸弹的半径化成的圆不能相交,求最大半径 二分半径, ...
- hdu1816 + POJ 2723开锁(二分+2sat)
题意: 有m层门,我们在最外层,我们要一层一层的进,每一层上有两把锁,我们只要开启其中的一把们就会开,我们有n组钥匙,每组两把,我们只能用其中的一把,用完后第二把瞬间就会消失,问你最多能开到 ...
- HDU3622 Bomb Game(二分+2-SAT)
题意 给n对炸弹可以放置的位置(每个位置为一个二维平面上的点), 每次放置炸弹是时只能选择这一对中的其中一个点,每个炸弹爆炸 的范围半径都一样,控制爆炸的半径使得所有的爆炸范围都不相 交(可以相切), ...
- 二分+2-sat——hdu3062
hdu3622升级版 注意要保留两位小数 /* 给定n对圆心(x,y),要求从每对里找到一个点画圆,不可相交 使得最小半径最大 二分答案,设最小半径为r 然后两两配对一次进行判断,在2-sat上连边即 ...
- hdu 3622 Bomb Game(二分+2-SAT)
Bomb Game Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- POJ 2296 二分+2-sat
题目大意: 给定n个点,给每个点都安排一个相同的正方形,使这个点落在正方形的下底边的中间或者上底边的中间,并让这n个正方形不出现相互覆盖,可以共享同一条边,求 这个正方形最大的边长 这里明显看出n个点 ...
- 【UVALive - 3211】Now or later (二分+2-SAT)
题意: 有n架飞机需要着陆.每架飞机有两种选择,早着陆或者晚着陆,二选其一.现在为了保证飞机的着陆安全,要求两架着陆的飞机的时间间隔的最小值达到最大. 分析: 最小值最大问题我们想到二分答案.对于猜测 ...
随机推荐
- 主机回来以及,简单的环境配置(RTX3070+CUDA11.1+CUDNN+TensorRT)
紧接着前几天的事: 特殊的日子,想起了当年的双(1080TI)显卡装机实录 和 炼丹炉买不起了:聊一聊这段日子的显卡行情 之后,决定买一台整机玩玩. 而现在,主机终于回!来!了!主机回来干什么,当然是 ...
- 2020 年安装 FreeBSD 系统的基础视频
B 站搜索 BV14i4y137mh 包含了下载,虚拟机安装,配置 SSH 等教程. https://www.bilibili.com/video/BV14i4y137mh
- WPF 基础 - 绘画 2) Path
1. Path 霸中霸 既可以替代其他几种图形,也可以将直线.圆弧.贝尔赛曲线组合起来; 重要属性:Geometry Data: 其中 Geometry 为抽象类,不可实例化,可使用其子类: Line ...
- hessian简单介绍
Hessian是基于HTTP的轻量级远程服务解决方案,Hessian像Rmi一样,使用二进制消息进行客户端和服务器端交互.但与其他二进制远程调用技术(例如Rmi)不同的是,它的二进制消息可以移植其他非 ...
- 模拟实现AMD模块化规范
目录 引子 再谈什么是闭包(闭包的产生)? 词法作用域 回到闭包 利用闭包编写模块 实现AMD模块化规范 写在最后 引子 本文最后的目的是模拟实现AMD模块化规范,而写下本文的原因是今天阅读到了< ...
- 画直线的算法之DDA算法+代码实现(法一)
DDA(数值微分法)基于直线微分方程生成直线. 点xi,yi满足直线方程yi=kxi+b, 若xi增加一个单位,则下一步点的位置(xi + 1,yi+1)满足yi+1=k(xi + 1)+ b. 即y ...
- C语言函数调用完整过程
C语言函数调用详细过程 函数调用是步骤如下: 按照调用约定传参 调用约定是调用方(Caller)和被调方(Callee)之间按相关标准 对函数的某些行为做出是商议,其中包括下面内容: 传参顺序:是从左 ...
- 使用 Android Studio 的日志工具 Log
•Log简介 Android中的日志工具类是Log,这个类中提供了5个方法来供我们打印日志: 1. $Log.v()$ 用于打印那些最为琐碎的,意义最小的日志信息 对应级别 verbose,是 And ...
- kong 结合 istio demo
- 盘点 Django 展示可视化图表的多种方式(建议收藏)
1. 前言 大家好,我是安果! 使用 Django 进行 Web 开发时,经常有需要展示图表的需求,以此来丰富网页的数据展示 常见方案包含:Highcharts.Matplotlib.Echarts. ...