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 【計算幾何 + 最短路】
- An Easy Problem?! POJ 2826 計算幾何
- POJ 2991 Crane(線段樹+計算幾何)
- POJ 1113 Wall(思維 計算幾何 數學)
- 計算幾何
- POJ 1127-Jack Straws(計算幾何 線段相交)
- POJ 1039-Pipe(計算幾何-線段相交、求交點)
- 計算幾何:模板
- 計算幾何模板
- [筆記] 計算幾何筆記
- 【計算幾何】向量表示
- 【總結】計算幾何模板
- 二維計算幾何模板
- 【計算幾何】線段相交
- 三維計算幾何模板
- Something about 計算幾何
- 計算幾何 —— 二維幾何基礎 —— 距離度量方法
- 邊緣計算、霧計算、雲端計算區別幾何?
- 【學習筆記】計算幾何筆記
- 計算幾何_向量的實現
- 【計算幾何】多邊形交集
- 計算幾何——平面最近點對
- POJ 3335-Rotating Scoreboard(計算幾何-半平面交順時針模板)
- POJ 1584-A Round Peg in a Ground Hole(計算幾何-凸包、點到線段距離)
- 計算幾何常用的函式/方法函式
- POJ 1408-Fishnet(計算幾何-根據交點求多邊形面積)
- BNUOJ 12887 isumi(計算幾何+最大流)
- SGU 124 Broken line(計算幾何)
- 【計算幾何】Triangles HUST 1607
- 【計算幾何】多邊形點集排序排序
- C++計算幾何演算法大全C++演算法
- 【計算幾何】點在多邊形內部
- POJ 3130-How I Mathematician Wonder What You Are!(計算幾何-星形-半平面交逆時針模板)
- 二維幾何常用運算
- SGU 120 SGU 228 Archipelago(計算幾何)Go
- 計算機視覺—圖片幾何變換(2)計算機視覺
- 【計算幾何】求線段相交交點座標
- BZOJ 1027 合金 計算幾何,Floyd判環