首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

POJ 1556 The Doors:計算幾何 + 最短路

     編輯:關於C++

問題描述

走廊寬 10,有 n 扇門,每扇門上下各有一個缺口(由兩條線段表示)。從左側 (0,5) 走到右側 (10,5),只能穿過門的缺口。求最短路徑長度。

解題思路

將所有缺口端點、起點、終點作為圖的頂點。若兩點連線段不與任何門的實體部分相交(即完全穿過缺口),則連邊,權重為歐氏距離。對 n 扇門,共 4n+2 個點。判斷線段是否穿過缺口:對每扇門,檢查線段是否與門的上下缺口線段相交(即不與實體牆相交)。構建圖後跑 Dijkstra/SPFA 求最短路。

代碼實現 (C++)

#include 
using namespace std;
const double EPS = 1e-8;
int dcmp(double x) { return (x > EPS) - (x < -EPS); }
struct Point { double x, y; };
using Vector = Point;
Vector operator-(Vector a, Vector b) { return {a.x-b.x, a.y-b.y}; }
double cross(Vector a, Vector b) { return a.x*b.y - a.y*b.x; }
double dot(Vector a, Vector b) { return a.x*b.x + a.y*b.y; }
double length(Vector a) { return sqrt(dot(a,a)); }
bool segIntersect(Point a1, Point a2, Point b1, Point b2) {
    double c1 = cross(a2-a1, b1-a1), c2 = cross(a2-a1, b2-a1);
    double c3 = cross(b2-b1, a1-b1), c4 = cross(b2-b1, a2-b1);
    return dcmp(c1)*dcmp(c2) <= 0 && dcmp(c3)*dcmp(c4) <= 0 &&
           max(a1.x,a2.x) >= min(b1.x,b2.x) - EPS &&
           max(b1.x,b2.x) >= min(a1.x,a2.x) - EPS &&
           max(a1.y,a2.y) >= min(b1.y,b2.y) - EPS &&
           max(b1.y,b2.y) >= min(a1.y,a2.y) - EPS;
}

struct Door { Point p[4]; }; // 0,1 上缺口; 2,3 下缺口
int n;
Door doors[30];
vector> G[130];
double dist[130];
bool vis[130];

bool canPass(int doorL, int doorR, Point a, Point b) {
    for (int i = doorL; i <= doorR; ++i) {
        // 檢查線段 a-b 是否與門 i 的實體牆相交
        // 實體牆 = 整個門寬 - 缺口。簡化:檢查是否同時穿過上缺口和下缺口的補集
        // 此處邏輯需根據題目精確建模,代碼略
    }
    return true; // 占位
}

double dijkstra(int s, int t) {
    fill(dist, dist+t+1, 1e100);
    dist[s] = 0;
    priority_queue, vector>, greater<>> pq;
    pq.emplace(0, s);
    while (!pq.empty()) {
        auto [d, u] = pq.top(); pq.pop();
        if (d > dist[u]) continue;
        if (u == t) return d;
        for (auto [v, w] : G[u]) {
            if (dist[v] > d + w) {
                dist[v] = d + w;
                pq.emplace(dist[v], v);
            }
        }
    }
    return -1;
}

int main() {
    while (cin >> n && n != -1) {
        for (int i = 0; i < n; ++i) {
            double x; cin >> x;
            for (int j = 0; j < 4; ++j) {
                double y; cin >> y;
                doors[i].p[j] = {x, y};
            }
        }
        // 構建圖:起點 0,終點 4n+1,中間 4n 個缺口端點
        // 省略具體構建邏輯
        printf("%.2f\n", dijkstra(0, 4*n+1));
    }
    return 0;
}

複雜度分析

  • 點數 ≤ 122,邊數 ≤ 122^2,Dijkstra O(V^2 log V) 或 O(E log V) 極快。
  • 幾何判斷 O(n) 每對點,總 O(V^2 * n) 可接受。

總結

計算幾何建模 + 圖最短路經典結合。關鍵在於正確判斷線段是否穿過所有門的缺口(即不與牆體相交)。線段相交判斷需注意精度與邊界情況。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved