ZOJ 3717 2-sat 进位精度

来源:互联网 发布:恶搞淘宝收件人名字 编辑:程序博客网 时间:2024/06/03 09:40

题意:

在三维空间中

给定n组,每组2个三维坐标 表示n组气球的中心坐标

问:

在每组中选取一个坐标,使得选出的n个坐标 有最大的半径(气球不能相交)

问最大的半径是多少

思路:

二分半径,2-sat判可行解

因为这不能四舍五入,所以最后要去掉误差后面的小数,然后暴力求解

 

 

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<math.h>#include<queue>using namespace std;#define hash Hash#define N 1000#define M 400000+5#define eps 1e-6//注意n是拆点后的大小 即 n <<= 1 N为点数(注意要翻倍) M为边数#define max(a,b) (a>b?a:b)struct Edge{int to, nex;}edge[M];int head[N], edgenum;void addedge(int u, int v){Edge E = {v, head[u]};edge[edgenum] = E;head[u] = edgenum ++;}bool mark[N];int Stack[N], top;void init(){memset(head, -1, sizeof(head)); edgenum = 0;memset(mark, 0, sizeof(mark));}bool dfs(int x){if(mark[x^1])return false;//一定是拆点的点先判断if(mark[x])return true;mark[x] = true;Stack[top++] = x;for(int i = head[x]; i != -1; i = edge[i].nex)if(!dfs(edge[i].to)) return false;return true;}bool solve(int n){for(int i = 0; i < n; i+=2)if(!mark[i] && !mark[i^1]){top = 0;if(!dfs(i)){while( top ) mark[ Stack[--top] ] = false;if(!dfs(i^1)) return false;}}return true;}struct node{double x,y,z;}p[N][2];double dist(node a,node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));}double dis[N][2][N][2];int hash(int i, int j, bool x){return (i*2+j)*2+1-x;}bool ok(double r, int n){init();int i, j, k, z;for(i = 0; i < n; i++)for(j = 0; j < 2; j++){addedge(hash(i,j,true),hash(i,j^1,false));addedge(hash(i,j,false),hash(i,j^1,true));}for(i = 0; i < n; i++)for(j = 0; j < 2; j++)for(k = 0; k < n; k++)if(i!=k)for(z = 0; z < 2; z++)if(dis[i][j][k][z] < r){addedge(hash(i,j,true),hash(k,z,false));}return solve(n<<2);}int main(){int i, j, n;while(~scanf("%d",&n)){for(i = 0; i < n; i++)for(j = 0; j < 2; j++)scanf("%lf %lf %lf",&p[i][j].x,&p[i][j].y,&p[i][j].z);for(i = 0; i < n; i++)for(j = 0; j < 2; j++)for(int k = 0; k < n; k++)for(int z = 0; z < 2; z++)dis[i][j][k][z] = dist(p[i][j],p[k][z])/2.0;double ans = 0, l = 0, r = 100000000;while(l+eps<r){double mid = (l+r)/2;if(ok(mid,n))l = ans = mid;else r = mid;}ans *= 1000.0; ans = floor(ans);ans/=1000.0;while(!ok(ans,n))ans-=0.001;while(ok(ans+0.001,n))ans+=0.001;printf("%.3lf\n", ans);}return 0;}/*21 1 1 5 5 51 1 1 5 5 5*/

0 0
原创粉丝点击