zzuoj 10413 && nyoj 1243 H.Radition Protection Wall 【几何 + 最短路】

10413: H.Radition Protection Wall

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值