POJ 1556 The Doors(Dijkstra+計算幾何)
The Doors
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 3338 | Accepted: 1440 |
Description
You are to find the length of the shortest path through a chamber containing obstructing walls. The chamber will always have sides at x = 0, x = 10, y = 0, and y = 10. The initial and final points of the path are always (0, 5) and (10, 5). There will also be from 0 to 18 vertical walls inside the chamber, each with two doorways. The figure below illustrates such a chamber and also shows the path of minimal length.

Input
The input data for the illustrated chamber would appear as follows.
2
4 2 7 8 9
7 3 4.5 6 7
The first line contains the number of interior walls. Then there is a line for each such wall, containing five real numbers. The first number is the x coordinate of the wall (0 < x < 10), and the remaining four are the y coordinates of the ends of the doorways in that wall. The x coordinates of the walls are in increasing order, and within each line the y coordinates are in increasing order. The input file will contain at least one such set of data. The end of the data comes when the number of walls is -1.
2
4 2 7 8 9
7 3 4.5 6 7
The first line contains the number of interior walls. Then there is a line for each such wall, containing five real numbers. The first number is the x coordinate of the wall (0 < x < 10), and the remaining four are the y coordinates of the ends of the doorways in that wall. The x coordinates of the walls are in increasing order, and within each line the y coordinates are in increasing order. The input file will contain at least one such set of data. The end of the data comes when the number of walls is -1.
Output
The output should contain one line of output for each chamber. The line should contain the minimal path length rounded to two decimal places past the decimal point, and always showing the two decimal places past the decimal point. The line should contain no blanks.
Sample Input
1 5 4 6 7 8 2 4 2 7 8 9 7 3 4.5 6 7 -1
Sample Output
10.00 10.06
Source
Mid-Central USA 1996
//Dijkstra+幾算幾何
//這道題的難點主要是在於如何構建一個圖
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double INF = 1 << 30;
const int N = 100;
struct node {
double x, y;
int r;
}pnt[N];
struct line {
node u, v;
}dr[N];
double m[N][N], d[N];
bool visited[N];
double dist(node n1, node n2) {
double x = n1.x - n2.x;
double y = n1.y - n2.y;
return sqrt(x * x + y * y);
}
double min(double a, double b) {
return a < b? a:b;
}
double max(double a, double b) {
return a > b? a:b;
}
double cross(node n1, node n2, node n0) {
double x = (n1.x - n0.x) * (n2.y - n0.y);
double y = (n1.y - n0.y) * (n2.x - n0.x);
return x - y;
}
bool intersect(node a, node b, node c, node d) {
bool f1 = (min(a.x, b.x) <= max(c.x, d.x));
bool f2 = (min(c.x, d.x) <= max(a.x, b.x));
bool f3 = (min(a.y, b.y) <= max(c.y, d.y));
bool f4 = (min(c.y, d.y) <= max(a.y, b.y));
bool f5 = (cross(a, c, d) * cross(c, b, d) >= 0);
bool f6 = (cross(d, a, b) * cross(a, c, b) >= 0);
return f1 && f2 && f3 && f4 && f5 && f6;
}
void dijkstra(int v, int n)
{
int i, j, k;
if(v < 0 || v > n) return;
for(i = 0; i <= n; i++) {
d[i] = m[v][i];
visited[i] = false;
}
d[v] = 0.0; visited[v] = true;
for(i = 1; i <= n; i++)
{
double min = INF;
k = v;
for(j = 0; j <= n; j++) {
if((!visited[j]) && (d[j] < min)) {
min = d[j];
k = j;
}
}
visited[k] = true;
for(j = 0; j <= n; j++) {
if((!visited[j]) && (m[k][j] < INF)) {
double newdist = d[k] + m[k][j];
if(newdist < d[j]) d[j] = newdist;
}
}
}
}
int main()
{
int i, j, k, n, cnt_1, cnt_2;
double x, y1, y2, y3, y4;
while(scanf("%d", &n) && n != -1) {
cnt_1 = 1; cnt_2 = 1;
for(i = 1; i <= n; i++)
{
scanf("%lf%lf%lf%lf%lf", &x, &y1, &y2, &y3, &y4);
pnt[cnt_1].x = x; pnt[cnt_1].y = y1; pnt[cnt_1].r = cnt_2; cnt_1++;
pnt[cnt_1].x = x; pnt[cnt_1].y = y2; pnt[cnt_1].r = cnt_2; cnt_1++;
dr[cnt_2].u = pnt[cnt_1-2]; dr[cnt_2].v = pnt[cnt_1-1]; cnt_2++;
pnt[cnt_1].x = x; pnt[cnt_1].y = y3; pnt[cnt_1].r = cnt_2; cnt_1++;
pnt[cnt_1].x = x; pnt[cnt_1].y = y4; pnt[cnt_1].r = cnt_2; cnt_1++;
dr[cnt_2].u = pnt[cnt_1-2]; dr[cnt_2].v = pnt[cnt_1-1]; cnt_2++;
}
pnt[0].x = 0; pnt[0].y = 5; pnt[0].r = 0;
pnt[cnt_1].x = 10; pnt[cnt_1].y = 5; pnt[cnt_1].r = cnt_2;
for(i = 0; i <= cnt_1; i++)
for(j = 0; j <= cnt_1; j++)
m[i][j] = INF;
for(i = 0; i <= cnt_1; i++)
{
int start = (pnt[i].r+1)/2*2+1;
for(j = i+1; j <= cnt_1; j++) {
if(pnt[i].x == pnt[j].x) continue;
int cnt = 0;
int end = (pnt[j].r+1)/2*2-1;
for(k = start; k < end; k++) {
if(intersect(pnt[i], pnt[j], dr[k].u, dr[k].v))
cnt++;
}
if(cnt+1 == (pnt[j].r+1)/2 - (pnt[i].r+1)/2)
m[i][j] = m[j][i] = dist(pnt[i], pnt[j]);
}
}
dijkstra(0, cnt_1);
printf("%.2lf\n", d[cnt_1]);
}
return 0;
}
//Dijkstra+幾算幾何
//這道題的難點主要是在於如何構建一個圖
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double INF = 1 << 30;
const int N = 100;
struct node {
double x, y;
int r;
}pnt[N];
struct line {
node u, v;
}dr[N];
double m[N][N], d[N];
bool visited[N];
double dist(node n1, node n2) {
double x = n1.x - n2.x;
double y = n1.y - n2.y;
return sqrt(x * x + y * y);
}
double min(double a, double b) {
return a < b? a:b;
}
double max(double a, double b) {
return a > b? a:b;
}
double cross(node n1, node n2, node n0) {
double x = (n1.x - n0.x) * (n2.y - n0.y);
double y = (n1.y - n0.y) * (n2.x - n0.x);
return x - y;
}
bool intersect(node a, node b, node c, node d) {
bool f1 = (min(a.x, b.x) <= max(c.x, d.x));
bool f2 = (min(c.x, d.x) <= max(a.x, b.x));
bool f3 = (min(a.y, b.y) <= max(c.y, d.y));
bool f4 = (min(c.y, d.y) <= max(a.y, b.y));
bool f5 = (cross(a, c, d) * cross(c, b, d) >= 0);
bool f6 = (cross(d, a, b) * cross(a, c, b) >= 0);
return f1 && f2 && f3 && f4 && f5 && f6;
}
void dijkstra(int v, int n)
{
int i, j, k;
if(v < 0 || v > n) return;
for(i = 0; i <= n; i++) {
d[i] = m[v][i];
visited[i] = false;
}
d[v] = 0.0; visited[v] = true;
for(i = 1; i <= n; i++)
{
double min = INF;
k = v;
for(j = 0; j <= n; j++) {
if((!visited[j]) && (d[j] < min)) {
min = d[j];
k = j;
}
}
visited[k] = true;
for(j = 0; j <= n; j++) {
if((!visited[j]) && (m[k][j] < INF)) {
double newdist = d[k] + m[k][j];
if(newdist < d[j]) d[j] = newdist;
}
}
}
}
int main()
{
int i, j, k, n, cnt_1, cnt_2;
double x, y1, y2, y3, y4;
while(scanf("%d", &n) && n != -1) {
cnt_1 = 1; cnt_2 = 1;
for(i = 1; i <= n; i++)
{
scanf("%lf%lf%lf%lf%lf", &x, &y1, &y2, &y3, &y4);
pnt[cnt_1].x = x; pnt[cnt_1].y = y1; pnt[cnt_1].r = cnt_2; cnt_1++;
pnt[cnt_1].x = x; pnt[cnt_1].y = y2; pnt[cnt_1].r = cnt_2; cnt_1++;
dr[cnt_2].u = pnt[cnt_1-2]; dr[cnt_2].v = pnt[cnt_1-1]; cnt_2++;
pnt[cnt_1].x = x; pnt[cnt_1].y = y3; pnt[cnt_1].r = cnt_2; cnt_1++;
pnt[cnt_1].x = x; pnt[cnt_1].y = y4; pnt[cnt_1].r = cnt_2; cnt_1++;
dr[cnt_2].u = pnt[cnt_1-2]; dr[cnt_2].v = pnt[cnt_1-1]; cnt_2++;
}
pnt[0].x = 0; pnt[0].y = 5; pnt[0].r = 0;
pnt[cnt_1].x = 10; pnt[cnt_1].y = 5; pnt[cnt_1].r = cnt_2;
for(i = 0; i <= cnt_1; i++)
for(j = 0; j <= cnt_1; j++)
m[i][j] = INF;
for(i = 0; i <= cnt_1; i++)
{
int start = (pnt[i].r+1)/2*2+1;
for(j = i+1; j <= cnt_1; j++) {
if(pnt[i].x == pnt[j].x) continue;
int cnt = 0;
int end = (pnt[j].r+1)/2*2-1;
for(k = start; k < end; k++) {
if(intersect(pnt[i], pnt[j], dr[k].u, dr[k].v))
cnt++;
}
if(cnt+1 == (pnt[j].r+1)/2 - (pnt[i].r+1)/2)
m[i][j] = m[j][i] = dist(pnt[i], pnt[j]);
}
}
dijkstra(0, cnt_1);
printf("%.2lf\n", d[cnt_1]);
}
return 0;
}
相關文章
- POJ - 1556 【計算幾何 + 最短路】
- POJ 1113 Wall(思維 計算幾何 數學)
- 計算幾何
- 計算幾何:模板
- 計算幾何模板
- POJ1847 Tram【Dijkstra+思維】
- Something about 計算幾何
- [筆記] 計算幾何筆記
- 計算幾何 —— 二維幾何基礎 —— 距離度量方法
- SGU 124 Broken line(計算幾何)
- 計算幾何——平面最近點對
- 【學習筆記】計算幾何筆記
- 邊緣計算、霧計算、雲端計算區別幾何?
- POJ1602 昂貴的聘禮【Dijkstra+列舉】
- BNUOJ 12887 isumi(計算幾何+最大流)
- SGU 120 SGU 228 Archipelago(計算幾何)Go
- POJ1511 Invitation Cards【Dijkstra+堆優化+前向星】優化
- 計算幾何(一):凸包問題(Convex Hull)
- HNOI2016礦區(計算幾何+對偶圖)
- 計算機視覺—圖片幾何變換(2)計算機視覺
- CodeForces 887 E. Little Brother(計算幾何+二分)
- [計算幾何]圓與三角形是否相交
- 百度造車,勝算幾何?
- [幾何]計算不規則多邊形的面積、中心、重心
- 【第一道計算幾何題】 UVA11178 Morley‘s Theorem (二維幾何,旋轉直線求求交點)REM
- 丘成桐演講全文:幾何與計算數學的關係
- 【IDL】幾何圖形數學運算函式函式
- 平面幾何
- 【POJ 2249】 Binomial Showdown 組合數學 排列組合計算
- 神奇的周幾計算器
- sql server 計算兩個時間 相差的 幾天幾時幾分幾秒SQLServer
- 《戴森球計劃》火了,“科幻遊戲”前途幾何?遊戲
- 恆訊科技分析:使用邊緣計算和雲端計算各有何優勢?
- 計算檔案Checksum的幾種方法
- 阿里美團戰事再升級:支付寶入局 勝算幾何?阿里
- 邊緣計算為何會如此受歡迎?
- CF2004B Game with Doors 題解GAM
- [計算機網路] - 從英雄聯盟,看資料包何去何從?計算機網路
- 在量子計算時代,企業資料的加密該何去何從?加密