F - Help!


题目描述:

F - Help!
Time Limit:2000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Submit

Status

Practice

HDU 5027
Appoint description:
Description
“Help! Help!”

While walking in the park, you suddenly hear someone shouting for help. You immediately realize that a person has fallen into the lake. As a brave man, you decide to save him.

You are really familiar with the terrain of the park. The park can be regarded as a 2D plane. And the lake is a convex polygon. At current, you are on (Xo, Yo), and the person is on (Xp, Yp). You also know that you can run Vr per second on the land, or swim Vs per second in the lake. Notice that you are allowed to run along the edge of the lake.

You are not good at swimming. You cannot stay in the lake longer than Ts second. And carrying another person will cut down your swimming speed by half.

Can you save the poor guy? What is the minimum time for you to reach him, and carry him back to the border of the lake?

Input
There are several test cases in the input.

The first line contains an integer T (1 <= T <= 20) – the number of test cases.

For each case:

The first line contains three real numbers Ts, Vr, Vs. 0 < Ts < 10 8, 0 < Vs < Vr < 10 8.

The second line contains two real numbers Xo, Yo, indicate the position (Xo, Yo) of you at current.

The third line contains two real numbers Xp, Yp, indicate the position (Xp, Yp) of the person you are going to save.

The forth line contains only one integer N – the number of vertices of the lake. 3 <= N <= 50000.

The follow N lines, each line contains two real numbers x, y, indicating one of the vertex (x, y) of the lake. The vertices of lake are listed in either clockwise or counter-clockwise order.

Each coordinate in the input does not exceed 10 6 by its absolute value. Your position is on the land and the person’s is in the lake.

Output
For each test case, output the minimum time(in seconds) to save the poor person, rounded to two digits after the decimal point. If you cannot save he, output “-1” instead.

Sample Input
2
100 2 1
0 10
0 0
3
-1 1
1 1
0 -1
1 2 1
0 10
0 0
3
-1 1
1 1
0 -1

Sample Output
6.39
-1

题解:

思路很简单.但是计算几何大爱啊….锻炼代码能力和敲代码时的脑容量(内存吧= =)
pre:先从终点找一条最短的出去的边,看能不能跑出去.然后把这个影响减去.
首先根据切点来把图上的点分成可以直接到达的和不能直接到达的.有一个分支注意:如果起点在图上,那么就没有切点.这个之后说.
切点可以画一个图,用叉积来判断.
对于搞出来的两个切点,自己利用上一步的叉积符号定义一个顺序,使得我们可以正确的扫能够直接到达的点(第一部分),不能直接到达的点(第二部分)

对于第一部分:我们枚举每一条线段,三分上面的点. 这里有一个特别需要注意的,我们在水里不能游太长时间是一个大前提,所以线段应该先被一个圆切割一下预处理再三分.

对于第二部分:我们发现要要么是先到切点0,然后绕凸多边形,要么是先到切点1,然后绕凸多边形, 我们分开去做,这样还能顺便满足三分的条件.做的时候因为有先绕的那一段距离,我们可以枚举的时候累加.

对于刚开始点在凸包上的情况,其实相当于都是第二部分的情况.先找到点在哪一个线段上,然后先特殊算一下这条线断上的值,然后跟第二部分一样算一下.

代码本来有一个continue提前打了,使得累计有时候没加上去…唉…continue 以后还是多用 {;} 这个玩意把.

重点:

会点和多边形相切的算法
想到三分和相切之后点的三分
想到在多边形上的特殊情况
想到线段三分前先处理下圆的要求

代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;

const double eps = 1e-4;
const int tim = 100;
const double INF = 1e100;
const int maxn = 50000+100;

int dcmp(double x)
{
    if(fabs(x) < eps)
        return 0;
    if(x > eps)
        return 1;
    return -1;
}
struct Point
{
    double x, y;
    Point(double _x = 0, double _y = 0)
    {
        x = _x;
        y = _y;
    }
    Point operator - (const Point &b)
    {
        return Point(x-b.x, y-b.y);
    }
    double operator ^  (const Point &b)
    {
        return x*b.y-y*b.x;
    }
    double operator * (const Point &b)
    {
        return x*b.x+y*b.y;
    }
    double mo()
    {
        return sqrt(x*x+y*y);
    }
};
double dist(Point a, Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double dist_Point_to_Line(Point o, Point a, Point b)
{
    if(dcmp((a-o)*(b-a))>0 || dcmp((b-o)*(a-b))>0)
    {
        return min(dist(a, o), dist(b, o));
    }
    return fabs(((a-o)^(b-o))/(b-a).mo());
}

Point p[maxn], oo, pp;
int qie[maxn], hc, fu[maxn], bg, ed;
int n;
double time_back, time_go;
double vr, vs, time_s_limit;

void getQie()
{
    hc = 0;
    for(int i = 0; i<n; i++)
    {
        int j = (i+1)%n;
        if(dcmp((p[j]-p[i])^(oo-p[i]))<0)
            fu[i] = 0;
        else
            fu[i] = 1;
    }
    for(int i = 0; i<n; i++)
    {
        int j = (i+1)%n;
        if(fu[i]!=fu[j])
        {
            qie[hc] = j;
            hc++;
        }
    }
}

double three_Search_Direct(Point a, Point b)
{
    Point ma, mb;
    double ansa, ansb;
    for(int i = 1; i<=tim; i++)
    {
        mb.x = (a.x+b.x)/2;
        mb.y = (a.y+b.y)/2;
        ma.x = (a.x+mb.x)/2;
        ma.y = (a.y+mb.y)/2;

        ansa = dist(ma, oo)/vr + dist(ma, pp)/vs;
        ansb = dist(mb, oo)/vr + dist(mb, pp)/vs;

        if(ansa-ansb>0)
            a = ma;
        else
            b = mb;
    }
    ansa = dist(a, oo)/vr + dist(a, pp)/vs;
    return ansa;
}
struct Line
{
    Point s, e;
};
bool OnSeg(Point P, Line L)
{
    return
        dcmp((L.s - P) ^ (L.e - P)) == 0 &&
        dcmp((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
        dcmp((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}
double three_Search_Undirect(Point a, Point b, double pre, Point pa)
{
    Point ma, mb;
    double ansa, ansb;
    for(int i = 1; i<=tim; i++)
    {
        mb.x = (a.x+b.x)/2;
        mb.y = (a.y+b.y)/2;
        ma.x = (a.x+mb.x)/2;
        ma.y = (a.y+mb.y)/2;

        ansa = (pre+dist(pa, ma))/vr + dist(ma, pp)/vs;
        ansb = (pre+dist(pa, mb))/vr + dist(mb, pp)/vs;

        if(ansa-ansb>0)
            a = ma;
        else
            b = mb;
    }
    ansa = (pre+dist(pa, a))/vr + dist(a, pp)/vs;
    //printf("&&&  %f %f --  %f  pre is %f  %f %f\n", a.x, a.y, ansa+time_back, pre, pa.x,pa.y);
    return ansa;
}

void circle_cross_line(Point a, Point b, double r, int &num, Point *res)
{
    double xa = a.x, ya = a.y, xb = b.x, yb = b.y;
    double dx = xb - xa, dy = yb - ya;
    double A = dx*dx + dy*dy, B = 2 * dx*xa + 2 * dy*ya, C = xa*xa + ya*ya -r*r;
    double delta = B*B - 4 * A*C;
    if (dcmp(delta)<0)
    {
        num = 0;
        return;
    }
    if (dcmp(delta) == 0)
    {
        double t1 = (-B) / (2 * A);
        if (dcmp(t1) >= 0 && dcmp(t1 - 1) <= 0)
        {
            num = 1;
            res[0] = Point(xa + t1*dx, ya + t1*dy);
            return;
        }
        else
        {
            num = 0;
            return;
        }
    }
    double t1 = (-B - sqrt(delta)) / (2 * A), t2 = (-B + sqrt(delta)) / (2*A);
    num = 0;
    if(dcmp(t2)<0 || dcmp(t1-1)>0)
    {
        num = 0;
    }
    else
    {
        double ta = max(0.0, t1), tb = min(1.0, t2);
        res[num] = Point(xa + ta*dx, ya + ta*dy);
        num++;
        res[num] = Point(xa + tb*dx, ya + tb*dy);
        num++;
    }
}
struct PointX
{
    Point p[3];
    int num;
};
PointX deal_Line_To_Line(Point a, Point b)
{
    //printf("**  %f  %f\n", a.x, a.y);
    //printf("**  %f  %f\n", b.x, b.y);
    PointX t;
    //printf("&&&  %f\n", time_s_limit*vs);
    circle_cross_line(a, b, time_s_limit*vs, t.num, t.p);
    return t;
}

void solve()
{
    for(int i = 0; i<n; i++)
    {
        p[i].x -= pp.x;
        p[i].y -= pp.y;
    }
    oo.x -= pp.x;
    oo.y -= pp.y;
    pp.x = 0;
    pp.y = 0;


    time_back = time_go = INF;
    p[n] = p[0];
    for(int i = 0; i<n; i++)
    {
        time_back = min(time_back, dist_Point_to_Line(pp, p[i], p[i+1])/vs*2.0);
    }

    if(dcmp(time_back-time_s_limit) > 0)
    {
        printf("-1\n");
        return;
    }
    //printf("**%f  %f\n", time_back, sqrt(5)/5.0);
    time_s_limit -= time_back;
    getQie();
    //printf("**%d\n", hc);
//    for(int i = 0;i<2;i++)
//    {
//        printf("**%f  %f\n", p[qie[i]].x, p[qie[i]].y);
//    }

    if(hc==0)
    {
        for(int i = 0; i<n; i++)
        {
            int j = (i+1)%n;
            Line t;
            t.s = p[i];
            t.e = p[j];
            if(OnSeg(oo, t))
            {
                qie[0] = i;
                qie[1] = j;
                PointX x;
                x = deal_Line_To_Line(oo, p[j]);
                if(x.num==0)
                {
                    ;
                }
                else if(x.num==1)
                {
                    time_go = min(time_go, dist(oo,x.p[0])/vr+dist(x.p[0],pp)/vs);
                }
                else
                {
                    time_go = min(time_go, three_Search_Undirect(x.p[0],x.p[1],0,oo));
                    //printf("time_go  %f\n", time_go+time_back);
                }

                x = deal_Line_To_Line(oo, p[i]);
                if(x.num==0)
                {
                    ;
                }
                else if(x.num==1)
                {
                    time_go = min(time_go, dist(oo, x.p[0])/vr+dist(x.p[0],pp)/vs);
                }
                else
                {
                    time_go = min(time_go, three_Search_Undirect(x.p[0],x.p[1],0,oo));
                }
                break;
            }
        }
    }
    else
    {
        if(fu[qie[0]]!=0)
            swap(qie[0], qie[1]);
        //printf("%d %d\n", qie[0], qie[1]);
        //printf("time_go  %f\n", time_go);
        int bg = qie[0], ed = qie[1];
        if(bg>ed)
            ed+=n;
        for(int i = bg; i<ed; i++)
        {
            int j = i+1;
            PointX t = deal_Line_To_Line(p[i%n], p[j%n]);
            //printf("***  %d %f %f  %f   %f\n", t.num, t.p[0].x,t.p[0].y,t.p[1].x,t.p[0].y);
            if(t.num==0)
                continue;
            if(t.num==1)
            {
                time_go = min(time_go, dist(oo, t.p[0])/vr+dist(t.p[0], pp)/vs);
            }
            else
            {
                time_go = min(time_go, three_Search_Direct(t.p[0], t.p[1]));
                //printf("----   %f\n", time_go);
            }
        }
        //printf("time_go  %f\n", time_go);
    }
    //printf("****************************%f\n", time_s_limit*3);
    bg = qie[1];
    ed = qie[0];
    double pre = dist(oo, p[bg]);
    //printf("mygirl  %f\n", dist(oo, p[2]), );
    //printf("now  %d  %d\n", bg, ed);
    for(int i = bg; (i)%n!=ed; i++)
    {
        //printf("iiii  %d\n", i);
        PointX t = deal_Line_To_Line(p[i%n], p[(i+1)%n]);
        if(t.num==0)
        {
            ;
        }
        else if(t.num==1)
        {
            time_go = min(time_go, pre+dist(p[i%n], t.p[0])/vr + dist(t.p[0],pp)/vs);
        }
        else
        {
            //printf("%f  %f  %f  %f %f\n", t.p[0].x,t.p[0].y,t.p[1].x,t.p[1].y, t.p[1].mo());
            time_go = min(time_go, three_Search_Undirect(t.p[0],t.p[1],pre, p[i%n]));
        }
        //printf("time_go  %f\n", time_go+time_back);
        pre += dist(p[i%n], p[(i+1)%n]);
    }
    bg = qie[0];
    ed = qie[1];
    pre = dist(oo, p[bg]);
    //printf("pp %f %f\n", pp.x,pp.y);
    //printf("big is %d  %d\n", bg, ed);
    for(int i = bg; (i+n)%n!=ed; i--)
    {
        //printf("iiii  %d\n", i);
        int ii = (i+n)%n;
        int jj = (ii-1+n)%n;
        PointX t = deal_Line_To_Line(p[ii], p[jj]);
        if(t.num==0)
        {
            ;
        }
        else if(t.num==1)
        {
            time_go = min(time_go, pre+dist(p[ii], t.p[0])/vr + dist(t.p[0],pp)/vs);
        }
        else
        {
            //printf("%f  %f  %f  %f %f\n", t.p[0].x,t.p[0].y,t.p[1].x,t.p[1].y, pre);
            time_go = min(time_go, three_Search_Undirect(t.p[0],t.p[1],pre, p[ii]));
        }
        pre += dist(p[ii], p[jj]);
        //printf("---- %d  %f\n",ii, time_go);
    }
    //printf("----   %f\n", time_go);
    if(dcmp(time_go-INF)==0)
        printf("-1\n");
    else
    {
        printf("%.2f\n", time_go+time_back);
    }
}
double poly_area(Point *p, int n)
{
    double ans = 0;
    for (int i = 1; i <= n - 2; i++)
    {
        ans += (p[i] - p[0]) ^ (p[i + 1] - p[0]);
    }
    return ans;
}

int main()
{
    //printf("****   %f\n", dist_Point_to_Line(Point(0,0),Point(1,0),Point(2,0)));
   // freopen("in.txt", "r", stdin);
    int ncase;
    scanf("%d", &ncase);
    while(ncase--)
    {
        scanf("%lf%lf%lf", &time_s_limit, &vr, &vs);
        scanf("%lf%lf", &oo.x, &oo.y);
        scanf("%lf%lf", &pp.x, &pp.y);
        scanf("%d", &n);
        for(int i = 0; i<n; i++)
        {
            scanf("%lf%lf", &p[i].x, &p[i].y);
        }
        double tmp = poly_area(p, n);
        if(dcmp(tmp)<0)
        {
            //printf("asdfasd");
            reverse(p, p+n);
        }
        solve();
        //printf("********************* %f\n", 3*sqrt(5));
    }
    return 0;
}
<think>我们遇到了一个错误:`argparse.ArgumentError: argument --help: conflicting option string: --help` 这个错误通常在使用Python的argparse模块时发生,原因是尝试添加一个已经存在的选项字符串。特别是,`--help`是argparse默认添加的一个选项,用于生成帮助信息。 当我们自己尝试添加一个名为`--help`的选项时,就会与内置的选项冲突,从而抛出这个异常。 解决方案: 避免添加与内置选项冲突的选项名。argparse默认会添加`-h`和`--help`选项。因此,我们不应该再添加一个`--help`选项。 但是,如果我们确实需要覆盖`--help`选项的行为(例如,自定义帮助信息),我们可以通过以下两种方式之一: 1. 在添加参数时,避免使用`--help`作为选项字符串。 2. 在创建ArgumentParser实例时,设置`add_help=False`来禁用默认的帮助选项,然后我们可以自定义一个`--help`选项。 下面是一个示例,展示如何自定义帮助选项: 假设我们想要添加一个`--help`选项,但是不想与默认的冲突,我们可以先禁用默认帮助,然后添加我们自己的。 但是请注意:通常我们不建议覆盖`--help`,因为用户期望它提供标准的帮助信息。如果确实需要,可以按照以下方式: ```python import argparse # 创建ArgumentParser对象时,设置add_help=False,禁用默认的-h/--help parser = argparse.ArgumentParser(description='自定义帮助示例', add_help=False) # 然后添加我们自己的帮助选项,例如使用'-H'和'--help' # 注意:这里我们使用两个选项字符串:-H和--help,这样用户既可以使用-H,也可以使用--help(覆盖了默认的--help) parser.add_argument('-H', '--help', action='help', default=argparse.SUPPRESS, help='显示帮助信息并退出') # 但是注意,上面的action='help'是argparse的一个内置动作,它会打印帮助信息并退出。然而,这样我们就没有默认的-h了。 # 或者,我们可以使用自定义的动作来处理--help,比如打印更详细的信息。 # 另一种做法是,我们使用不同的选项字符串,避免使用--help,比如使用'--hlp'等。 # 然而,如果我们坚持要使用--help,并且自定义行为,可以这样做: # 例如,我们自定义一个动作,当用户输入--help时,我们打印一些额外的信息。 class CustomHelpAction(argparse.Action): def __init__(self, option_strings, dest, **kwargs): super().__init__(option_strings, dest, **kwargs) def __call__(self, parser, namespace, values, option_string=None): # 在这里自定义帮助信息 print("这是自定义的帮助信息!") print("以下是我们支持的参数:") parser.print_help() parser.exit() # 退出程序 # 然后添加参数 parser.add_argument('--help', action=CustomHelpAction, nargs=0, help='显示自定义帮助信息') # 但是这样会覆盖掉我们之前通过add_help=False禁用的帮助,现在我们可以用这个自定义的帮助。 # 但是注意,这样我们就不能使用-h了,因为默认的-h已经被禁用了。我们可以再添加一个-h的选项。 # 添加一个-h选项,指向同一个动作 parser.add_argument('-h', action=CustomHelpAction, nargs=0, help='同--help') # 这样,我们就自定义了-h和--help的行为。 但是,通常我们不需要自定义帮助信息到这种程度。更常见的做法是使用默认的帮助,然后通过修改description和epilog来定制帮助文本。 因此,回到最初的问题:如果我们在代码中不小心添加了一个名为`--help`的选项,那么我们应该删除它,或者更改选项字符串。 例如,错误代码可能是这样的: ```python parser.add_argument('--help', ...) # 这会导致冲突 ``` 我们应该将其改为其他名称,例如: ```python parser.add_argument('--hlp', ...) ``` 或者,如果我们确实需要覆盖帮助选项,那么按照上面的方法,先禁用默认帮助,再添加自定义的。 下面是一个简单的示例,展示如何避免冲突: 错误示例(会导致ArgumentError): ```python import argparse parser = argparse.ArgumentParser() parser.add_argument('--help', action='store_true', help='This will cause conflict') # 错误 ``` 正确做法1:避免使用--help ```python import argparse parser = argparse.ArgumentParser() parser.add_argument('--show-help', action='store_true', help='Show help message') # 改为其他名称 ``` 正确做法2:禁用默认帮助,然后自定义(但通常不推荐,因为用户习惯标准的帮助选项) ```python import argparse # 禁用默认帮助 parser = argparse.ArgumentParser(add_help=False) # 添加自定义的帮助选项 parser.add_argument('-h', '--help', action='store_true', help='Show custom help') # 然后,在解析参数后,如果用户输入了--help,我们可以手动打印帮助 args = parser.parse_args() if args.help: parser.print_help() exit(0) ``` 但是,上面的自定义帮助会丢失argparse自动生成的帮助信息格式,而且需要自己处理打印和退出。所以,更推荐使用argparse内置的`action='help'`,但注意这个动作需要我们在添加参数时指定,并且需要禁用默认帮助。 内置的help动作示例: ```python import argparse parser = argparse.ArgumentParser(add_help=False) # 添加一个选项,当用户输入-h或--help时,触发帮助动作 parser.add_argument('-h', '--help', action='help', default=argparse.SUPPRESS, help='Show this help message and exit') # 这样,当用户输入-h或--help时,就会打印帮助信息并退出。 ``` 总结:避免添加与默认选项冲突的参数,或者禁用默认帮助后再添加自定义帮助。 现在,我们给出一个具体的代码示例,演示如何正确地自定义帮助选项(使用内置的help动作):</think>### 解决 `argparse.ArgumentError: argument --help: conflicting option string: --help` 这个错误发生在使用 Python 的 `argparse` 模块时,尝试添加一个与内置选项冲突的自定义参数(如 `--help`)。`argparse` 默认会添加 `-h/--help` 参数用于生成帮助信息,如果用户代码中重复定义 `--help`,就会引发冲突。 --- ### 解决方案 #### 方法 1:避免使用 `--help`(推荐) 直接修改自定义参数的名称(例如改为 `--custom-help`),避开保留关键字: ```python import argparse parser = argparse.ArgumentParser() # 使用非冲突名称(如 --custom-help) parser.add_argument("--custom-help", action="store_true", help="Custom help message") args = parser.parse_args() if args.custom_help: print("This is custom help!") ``` #### 方法 2:禁用默认帮助选项 在初始化 `ArgumentParser` 时设置 `add_help=False`,然后自定义帮助逻辑: ```python import argparse # 禁用默认帮助选项 parser = argparse.ArgumentParser(add_help=False) # 添加自定义的 --help 参数 parser.add_argument("--help", action="store_true", help="Show custom help") # 添加其他参数 parser.add_argument("--input", type=str, help="Input file") args = parser.parse_args() if args.help: print("### CUSTOM HELP ###") parser.print_help() # 手动打印帮助信息 exit(0) # 正常业务逻辑 print(f"Processing input: {args.input}") ``` --- ### 关键解释 1. **冲突原因**: - `argparse` 自动注册 `-h/--help` 作为帮助参数。 - 用户代码中重复定义 `parser.add_argument("--help", ...)` 会导致键冲突。 2. **`add_help=False` 的作用**: - 禁用内置的 `-h/--help` 参数,允许安全使用 `--help` 作为自定义参数。 3. **自定义帮助的实现**: - 通过 `action="store_true"` 捕获 `--help` 的调用。 - 使用 `parser.print_help()` 手动打印帮助信息并退出。 --- ### 示例输出 ```bash $ python script.py --help ### CUSTOM HELP ### usage: script.py [-h] [--input INPUT] options: -h, --help Show custom help --input INPUT Input file ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值