[2-sat]动态的2-sat问题(hdu3622)

来源:互联网 发布:淘宝店刷销量多少钱 编辑:程序博客网 时间:2024/05/16 06:58

概述

在一些最优化的问题当中,我们不知道一些指标的最优值是多少,而这个指标又在影响我们的逻辑表达式,我觉得这样的问题是一种动态的2-sat问题。通常,我们使用搜索,不断的重复建图,最后达到解题的目标。

一个例题

这是ACM亚洲区比赛的一题:
Robbie is playing an interesting computer game. The game field is an unbounded 2-dimensional region. There are N rounds in the game. At each round, the computer will give Robbie two places, and Robbie should choose one of them to put a bomb. The explosion area of the bomb is a circle whose center is just the chosen place. Robbie can control the power of the bomb, that is, he can control the radius of each circle. A strange requirement is that there should be no common area for any two circles. The final score is the minimum radius of all the N circles.
Robbie has cracked the game, and he has known all the candidate places of each round before the game starts. Now he wants to know the maximum score he can get with the optimal strategy.
我们的思路:
显然,这是一个最优化的问题,每一步的两个点,我们只可以选一个,就好像一个逻辑变量一样。但是,我们该怎样构建逻辑表达式,也就是如何建图呢?很显然,这个我们所规定的最大半径有关,如果两个点间的距离小于我们所要求的半径,那么两个圆就是存在重叠面积的,这样的话两个点就不可以被同时选择。
二分搜索半径的大小,并且不断建图判断逻辑表达式的可解性,最后可以得到最优解。
不过这题最难的是精度啊。。。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>#include<queue>#include<cmath>using namespace std;#define MAXN 205#define MAXM 405#define ZERO 10e-5struct CPoint{    double x,y;}PointList[MAXN];struct Edge{    int to;    int next;}EdgeTable[MAXN*MAXN];int head[MAXN];int dfn[MAXN],low[MAXN],match[MAXN];int state[MAXN];int e,n,cnt,curT;stack<int>S;double O_dis(CPoint a,CPoint b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}void addEdge(int from,int to){    EdgeTable[e].to=to;    EdgeTable[e].next=head[from];    head[from]=e++;}void get_Graph(double num){    int i,j;    memset(head,-1,sizeof(head));    e=0;    for(i=0;i<n;i++){        for(j=i+1;j<n;j++){        //the points in the same round should not be compared            if(O_dis(PointList[2*i],PointList[2*j])-2*num<-ZERO){                addEdge(2*i,2*j+1);                addEdge(2*j,2*i+1);            }            if(O_dis(PointList[2*i],PointList[2*j+1])-2*num<-ZERO){                addEdge(2*i,2*j);                addEdge(2*j+1,2*i+1);            }            if(O_dis(PointList[2*i+1],PointList[2*j])-2*num<-ZERO){                addEdge(2*i+1,2*j+1);                addEdge(2*j,2*i);            }            if(O_dis(PointList[2*i+1],PointList[2*j+1])-2*num<-ZERO){                addEdge(2*i+1,2*j);                addEdge(2*j+1,2*i);            }        }    }    return;}void Dfs(int cur){    low[cur]=dfn[cur]=curT++;    state[cur]=1;    S.push(cur);    int i;    for(i=head[cur];i!=-1;i=EdgeTable[i].next){        int dest = EdgeTable[i].to;        if(!state[dest]){            Dfs(dest);            low[cur] = min(low[cur],low[dest]);        }        else if(state[dest]==1)            low[cur] = min(low[dest],low[cur]);    }    if(low[cur]==dfn[cur]){        while(!S.empty()){            int d = S.top();            S.pop();            match[d]=cnt;            state[d]=2;            if(d==cur)break;        }        cnt++;    }    return;}bool Solve(){    memset(state,0,sizeof(state));    cnt=0;    int i;    for(i=0;i<2*n;i++){        if(!state[i]){            curT=0;            Dfs(i);        }    }    for(i=0;i<n;i++){        if(match[2*i]==match[2*i+1])            return false;    }    return true;}int main(){    freopen("input","r",stdin);    int i,j;    double maxdis;    while(scanf("%d",&n)!=EOF){        maxdis=-1.0;        for(i=0;i<2*n;i++){            scanf("%lf %lf",&PointList[i].x,&PointList[i].y);            for(j=i-1;j>=0;j--)                maxdis=max(maxdis,O_dis(PointList[i],PointList[j]));        }        double L=0.0,R=maxdis+0.1,ans=0.0;        while((R-L)>=ZERO){        //apply binary search to find answer            double mid=(L+R)/2;            get_Graph(mid);            //printf("%.2lf\n",mid);            if(Solve()){                L=mid+ZERO;                ans=mid;            }            else                R=mid-ZERO;        }        printf("%.2f\n",ans);    }    return 0;}
0 0
原创粉丝点击