10413: H.Radition Protection Wall
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1 Solved: 1
[ Submit][ Status][ Web Board]
Description
A military base in the tested nuclear weapons, an explosion because of failure. In order to prevent nuclear radiation leakage, it is necessary to establish a closed house.
The closed house is a convex polygon in the wall, will be constructed of N or fewer connected straight wall segments (3 <= N <=100), forming a polygon which contains the location of the nuclear leak (X0,Y0).
Due to the complex terrain of the military base and the cost , the chief has obtained from his contractor a list of prices for building wall segments at various locations. He could potentially build N different wall segments, and he knows the coordinates of the endpoints and cost for each of these segments. The location of the nuclear leak does not lie on any endpoints (X,Y) coordinates between -10000 and 10000, and does not lie directly on any of the potential wall segments.
Determine the minimum-cost set of wall segments that forms a convex polygon containingthe location of the nuclear leak.
Input
The input contains K test cases (1<=K<=5). Each test case specifies:
* Line 1: N X0 Y0
* Lines 2..N+1: Five space-separated integers describing a potential wall segment.
the first two integers are the X and Y,coordinates of one endpoint;
the next two integers are the X and Y coordinates of the second endpoint; the last integer is the cost C of building that wall (1 <= C <= 10000).
Output
For each test case generate a single line containing a single integer that is the cost of the cheapest set of walls which form a legal prison or -1 if no such prison can be constructed
Sample Input
1
8 1 1
0 0 0 3 2
0 0 3 1 2
3 1 2 3 2
0 3 1 2 1
1 2 2 3 1
0 3 2 3 4
1 2 0 0 8
3 1 0 3 8
Sample Output
10
HINT
Use the first, second, third, and sixth walls.
题意:给你n条线段以及选用每条线段的代价,要求你构建一个凸多边形围成点(x, y),该点不能在构建的凸多边形上。问你最小的代价,若无法构建输出-1。
思路:叉积选边,判断建边时要分四种情况,还有在选边的时候要把点(x, y)考虑进去即选好的边包围点(x, y)。然后建好图,对每条线段,以该线段为起点跑一次最短路维护最优值即可,在最短路的时候如果没有添加超级汇,那么在预处理的时候,不能标记起点。
时间复杂度O(n^3),足够了。
注意:线段包含建边是不能建边的,包含与被包含的两条线段可以构成一个回路。不判断这点也能过。。。
在zzuoj1A,在nyojWA死了,最后才发现可能有多条线段端点相同,代价不同。说好的不同的N条线段呢?
不过,这两个oj的数据较弱,建议AC后自己想几组好的数据。
给出几组我找的数据,其它的写在一张纸上貌似找不到了。 o(╯□╰)o
100
10 1 1
0 0 0 3 2
0 0 0 3 2
0 0 0 3 2
0 0 3 1 2
3 1 2 3 2
0 3 1 2 1
1 2 2 3 1
0 3 2 3 4
1 2 0 0 8
3 1 0 3 8
3 0 0
0 0 3 3 1
0 0 0 3 1
0 3 3 3 1
5 0 1
0 0 -1 -1 1
0 0 3 3 1
0 0 0 3 1
-1 -1 0 3 1
0 3 3 3 1
8 3 1
0 0 0 1 1
0 1 1 2 1
1 2 2 1 1
2 1 3 2 1
3 2 4 1 1
4 1 4 0 1
0 0 4 0 1
4 0 2 1 1
6 1 1
0 0 0 2 1
0 2 2 2 1
0 0 2 0 3
2 0 2 2 1
0 0 1 0 1
1 0 2 0 1
9 1 1
0 0 0 3 2
0 0 3 1 2
3 1 2 3 2
0 3 1 2 1
1 2 2 3 1
0 3 2 3 4
1 2 0 0 8
3 1 0 3 8
0 0 0 3 1
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (100+10)
#define MAXM (500000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
struct Point{
int x, y;
Point(){};
Point(int X, int Y){
x = X; y = Y;
}
};
Point operator - (Point A, Point B){
return Point(A.x-B.x, A.y-B.y);
}
bool operator == (Point A, Point B){
return A.x == B.x && A.y == B.y;
}
int Cross(Point A, Point B){
return A.x*B.y - A.y*B.x;
}
int Dot(Point A, Point B){
return A.x*A.y - B.x*B.y;
}
struct Line{
Point s, e;
int cost;
Line(){};
Line(Point A, Point B){
s = A; e = B;
}
};
Line L[MAXN];
int Map[MAXN][MAXN], dist[MAXN];
bool vis[MAXN];
int dijkstra(int s, int e, int n)
{
for(int i = 0; i < n; i++)
{
dist[i] = Map[s][i];
vis[i] = false;
}
//vis[s] = true;
for(int i = 1; i < n; i++)
{
int Min = INF, next = i;
for(int j = 0; j < n; j++)
{
if(!vis[j] && Min > dist[j])
{
Min = dist[j];
next = j;
}
}
vis[next] = true;
for(int j = 0; j < n; j++)
if(!vis[j])
dist[j] = min(dist[j], Map[next][j] + dist[next]);
}
return dist[e];
}
bool judge(Line A, Line B, Point P)
{
if(Cross(A.e-A.s, B.s-A.s) == 0 && Cross(A.e-A.s, B.e-A.s) == 0)//一条线段被另一条线段包含 不处理
{
if(min(A.s.x, A.e.x) >= min(B.s.x, B.e.x) && max(A.s.x, A.e.x) <= max(B.s.x, B.e.x)
|| min(B.s.x, B.e.x) >= min(A.s.x, A.e.x) && max(B.s.x, B.e.x) <= max(A.s.x, A.e.x))
return false;
}
if(A.s == B.s)
{
if(Cross(A.s-A.e, B.e-B.s) >= 0 && Cross(B.e-B.s, P-B.e) > 0)
return true;
}
if(A.s == B.e)
{
if(Cross(A.s-A.e, B.s-B.e) >= 0 && Cross(B.s-B.e, P-B.s) > 0)
return true;
}
if(A.e == B.s)
{
if(Cross(A.e-A.s, B.e-B.s) >= 0 && Cross(B.e-B.s, P-B.e) > 0)
return true;
}
if(A.e == B.e)
{
if(Cross(A.e-A.s, B.s-B.e) >= 0 && Cross(B.s-B.e, P-B.s) > 0)
return true;
}
return false;
}
bool OnSegment(Point P, Line A){
return Cross(A.s-P, A.e-P) == 0 && Dot(A.s-P, A.e-P) <= 0;
}
int main()
{
int t; Ri(t);
W(t)
{
int n, x0, y0; Ri(n); Ri(x0); Ri(y0);
Point P = Point(x0, y0);
for(int i = 0; i < n; i++)
{
Ri(L[i].s.x); Ri(L[i].s.y);
Ri(L[i].e.x); Ri(L[i].e.y);
Ri(L[i].cost);
}
CLR(Map, INF);
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
if((L[i].s == L[j].s && L[i].e == L[j].e) || (L[i].s == L[j].e && L[i].e == L[j].s)) continue;
if(judge(L[i], L[j], P))
Map[i][j] = min(Map[i][j], L[j].cost);
}
}
int ans = INF;
for(int i = 0; i < n; i++)
ans = min(ans, dijkstra(i, i, n));
if(ans == INF)
Pi(-1);
else
Pi(ans);
}
return 0;
}