HDU 4606 Occupy Cities (計算幾何+最短路+最小路徑覆蓋)
轉載請註明出處,謝謝http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
題目:給出n個城市需要去佔領,有m條線段是障礙物,有p個士兵可以用。佔領城市有個先後順序,每個士兵有個揹包,佔領城市之後,僅能補給一次揹包。問揹包容量最少是多少,可以用這P個士兵完成任務,起點任意 。
http://acm.hdu.edu.cn/showproblem.php?pid=4606
首先:列舉所有頂點,求一下距離,判斷是否與線段相交。然後 floyd預處理最短路
之後是二分答案,判斷是否可達
根據佔領的先後順序建邊,根據二分的值判斷不需要補給是否能夠到達。
之後便是判斷最小路徑覆蓋數是否小於等於P。
#include <iostream>
#include <queue>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const int N = 505;
const int M = 3000000;
const int INF = 100000;
const double eps = 1e-7;
inline int dcmp(double d){
return d < -eps? -1 : d > eps;
}
inline double sqr(double d){
return d * d;
}
struct Point {
double x, y;
Point (){}
Point (double _x,double _y):x(_x),y(_y){}
inline bool operator == (const Point &p)const {
return (dcmp(x - p.x) == 0 && dcmp(y - p.y) == 0);
}
inline Point operator - (const Point &p)const {
return Point(x - p.x,y - p.y);
}
inline double operator * (const Point &p)const {
return x * p.y - y * p.x;
}
inline double operator / (const Point &p)const {
return x * p.x + y * p.y;
}
inline double Distance(Point p){
return sqrt(sqr(p.x - x) + sqr(p.y - y));
}
void input(){
scanf ("%lf %lf", &x, &y);
}
}p[N];
struct Line{
Point a,b;
void input(){
a.input();
b.input();
}
Line(){}
Line(Point _a,Point _b):a(_a),b(_b){}
inline bool operator == (const Line &l) const{
return (a == l.a && b == l.b) || (a == l.b && b == l.a);
}
inline double operator * (const Point &p)const {
return (b - a) * (p - a);
}
inline double operator / (const Point &p)const {
return (p - a) / (p - b);
}
inline int SegCrossSeg(const Line &v){
int d1 = dcmp((*this) * v.a);
int d2 = dcmp((*this) * v.b);
int d3 = dcmp(v * a);
int d4 = dcmp(v * b);
if((d1 ^ d2) == -2 && (d3 ^ d4) == -2) return 2;
return ((d1 == 0 && dcmp((*this) / v.a) <= 0)
||(d2 == 0 && dcmp((*this) / v.b) <= 0)
||(d3 == 0 && dcmp(v / a) <= 0)
||(d4 == 0 && dcmp(v / b) <= 0) );
}
}l[N];
int n , m , K , seq[N];
int match[N], vis[N];
double dist[N][N];
int tot , start[N];
struct Edge {
int v, next;
}e[N * N];
void _add (int u , int v) {
e[tot].v = v;
e[tot].next = start[u];
start[u] = tot ++;
}
bool dfs (int u) {
for (int i = start[u] ; i != -1 ; i = e[i].next) {
int v = e[i].v;
if (! vis[v]) {
vis[v] = 1;
if(match[v] == -1 || dfs(match[v])) {
match[v] = u;
return true;
}
}
}
return false;
}
int hungry () {
int ans = 0;
memset (match , -1, sizeof(match)) ;
for (int i = 1 ; i <= n ; i ++) {
memset (vis , 0 , sizeof(vis));
if (dfs(i)) ans ++;
}
return ans;
}
bool check (double mid) {
tot = 0 ;
memset (start , -1 , sizeof(start));
for (int i =1 ; i <= n ; i ++) {
for (int j = i + 1 ; j <= n ; j ++) {
if(dist[seq[i]][seq[j]] <= mid)
_add (seq[i] , seq[j] + n);
}
}
return n - hungry() <= K;
}
double solve(){
double l = 0 , r = INF;
double ans = -1;
int cnt = 50;
while(cnt --){
double mid = (l + r) * 0.5;
if(check(mid)){
ans = mid;
r = mid;
}
else l = mid;
}
return ans;
}
int main(){
int t;
scanf ("%d", &t);
while (t --){
scanf ("%d%d%d", &n, &m, &K);
for (int i = 1 ; i <= n ; i ++){
p[i].input();
}
for (int i = 1 ; i <= m ; i ++){
l[i].input();
p[n + (i - 1) * 2 + 1] = l[i].a;
p[n + i * 2] = l[i].b;
}
for (int i = 1 ; i <= n + m * 2 ; i ++){
for (int j = 1 ; j <= n + m * 2 ; j ++){
if(i == j) dist[i][j] = 0.0;
else {
bool flag = false;
for (int k = 1 ; k <= m ; k ++){
if(l[k] == Line(p[i] , p[j])) continue;
if (l[k].SegCrossSeg(Line(p[i] , p[j])) == 2) {
flag = true;
break ;
}
}
if(flag) dist[i][j] = 1e9;
else dist[i][j] = p[i].Distance(p[j]);
}
}
}
for(int i = 1;i <= n;i ++){
scanf("%d",&seq[i]);
}
for (int k = 1 ; k <= n + m * 2 ; k ++) {
for (int i = 1 ; i <= n + m * 2 ; i ++) {
for (int j = 1 ; j <= n + m * 2 ;j ++ ){
dist[i][j] = fmin(dist[i][j] , dist[i][k] + dist[k][j]);
}
}
}
double ans = solve();
printf("%.2f\n",ans);
}
return 0;
}
相關文章
- 最小路徑可重複點覆蓋
- POJ - 1556 【計算幾何 + 最短路】
- 最大匹配、最小頂點覆蓋、最大獨立集、最小路徑覆蓋(轉)(再轉)
- poj2594Treasure Exploration【最小路徑覆蓋+floyd傳遞閉包】
- 洛谷OJ:P2764 最小路徑覆蓋問題(網路流)
- HDU3665Seaside(最短路徑)IDE
- 計算幾何
- HDU 4643 GSM(計算幾何求線段的中垂線)
- Floyd演算法(計算最短路徑)演算法
- 計算幾何:模板
- 計算幾何模板
- HDU 1077Catching Fish(簡單計算幾何)
- 涵蓋最廣的計算機程式設計學習資料計算機程式設計
- [筆記] 計算幾何筆記
- HDU 6055 Regular polygon(幾何)Go
- JaCoCo計算程式碼覆蓋率原理
- 單元測試的覆蓋率計算
- 【計算幾何】向量表示
- 【總結】計算幾何模板
- 二維計算幾何模板
- 【計算幾何】線段相交
- 三維計算幾何模板
- Something about 計算幾何
- Points on Cycle (hdu1700,幾何)
- 幾個最短路徑的演算法演算法
- 計算幾何 —— 二維幾何基礎 —— 距離度量方法
- 邊緣計算、霧計算、雲端計算區別幾何?
- 【學習筆記】計算幾何筆記
- 計算幾何_向量的實現
- 【計算幾何】多邊形交集
- 計算幾何——平面最近點對
- An Easy Problem?! POJ 2826 計算幾何
- 計算幾何常用的函式/方法函式
- HDU3790 最短路徑問題【Dijkstra演算法】演算法
- hdu5365 簡單幾何問題
- hdu 2150- Pipe-解析幾何
- 【測繪程式設計試題集】 試題04 最短路徑計算程式設計
- 智慧景區無線AP覆蓋方案的成本計算