hdu3622 二分+2sat
生活随笔
收集整理的這篇文章主要介紹了
hdu3622 二分+2sat
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ?給你N組炸彈,每組2個,讓你在這N組里面選取N個放置,要求(1)每組只能也必須選取一個(2)炸彈與炸彈之間的半徑相等(3)不能相互炸到對方。求最大的可放置半徑。
思路:
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
? ? ?給你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; }
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的hdu3622 二分+2sat的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu1824 基础2sat
- 下一篇: hdu3715 二分+2sat+建图