zoukankan      html  css  js  c++  java
  • jzoj3297. 【SDOI2013】逃考

    Description

    高考又来了,对于不认真读书的来讲真不是个好消息。为了小杨能在家里认真读书,他的亲戚决定驻扎在他的家里监督他学习,有爷爷奶奶、外公外婆、大舅、大嫂、阿姨……
    小杨实在是忍无可忍了,这种生活跟监狱有什么区别!为了他亲爱的小红,为了他的dota,他决定越狱!
    假设小杨的家是个n*m 的矩阵,左下角坐标为(0,0),右上角坐标为(x1,y1)。小杨有n 个亲戚,驻扎在矩阵里(位置不同,且不在矩阵的边上)。小杨家里的每个地方都被亲戚监控着,而且只被距离最近的亲戚监控:
    也就是说假设小杨所在的位置是(3,3),亲戚A 在(3,0),A 距离小杨距离是3;亲戚B 在(6,7),则B 距离小杨距离是5。距离A < 距离B,所以(3,3)位置由A 监控。
    如果“最近距离”出现同时有几个亲戚,那么那个位置同时被那几个亲戚监控。
    给出小杨的坐标(x0,y0)。因为被发现的人数越少,越狱成功的机会越大,所以小杨需要你设计一条越狱路线到达矩形的边上,且被发现的人数最少。
    Ps:小杨做的方向是任意的,也就是说路线上的任意位置只需要是实数。
    保证一开始小杨只被一个亲戚监控着。

    Input

    第一行,一个正整数t<=3,表示数据个数。
    接下来t 个数据:
    第一行n,表示小杨的亲戚个数。
    接下来一行四个正整数,表示矩形右上角的坐标(x1,y1)和小杨的坐标(x0,y0)。
    接下来n 行,每行两个正整数,代表一个亲戚的位置。

    Output

    每个数据输出一个正整数,表示小杨越狱被发现人数的最小值。

    Sample Input

    3
    4
    10 10 5 5
    5 6
    3 5
    7 5
    5 3
    0
    10 10 5 5
    3
    3 3 2 2
    1 1
    2 2
    2 1

    Sample Output

    1
    0
    1

    Data Constraint

    前50%数据,n<=200;
    其余数据n<=600。

    Hint

    样例解释:
    第一个数据,小杨直接往上走,只被(5,6)监控过。
    第二个数据,小杨被(7,7)监控,走到(9,9)被(7,11)监控,然后直接往上走。

    题解

    此题再次证实——比赛千万别死磕计算几何
    虽然我也只是磕了2个小时
    题意应该很好懂。
    一个显然的性质:
    为了便于逃跑,小杨尽量往亲戚点跑,经过的亲戚可能性越小~~(最危险的地方最安全)~~
    我们有一个很容易想到的方法:
    考虑建图,把任意两个亲戚间互相到达的最小代价求出来,跑最短路即可。
    怎么求是个问题。
    我们看到一个性质——
    对于两个亲戚,当且仅当小杨走到两点线段间的中垂线时,才是被两个亲戚同时监控。
    一个直观的想法——这个中垂线是否可以当分界线呢?
    由于一个中垂线把平面分成两半,于是我们可以考虑到对于一个i,把i与其他亲戚的所有中垂线求出来。
    然后,可以发现,这些中垂线可以围成一个区域,而这个区域则是当且亲戚i所控制的区域。
    这不是显然半平面交吗?
    直接暴力搞。时间不多。
    搞出来有什么用呢?
    我们又发现,如果小杨从i通过半平面交上一条i与j之间的中垂线到达j,代价是花费1的。
    不就可以建图连边了吗?
    完美解决。

    问题来了,这么找到结束的点的位置?
    直接把矩形的四条边丢进半平面交即可。
    当然,细节极多,调了我近3h。

    标程

    代码不多,也就9k
    不多不多,多乎哉,不多也。

    type
            nod=record
                    x,y:real;
            end;
            point=record
                    x,y:real;
            end;
            line=record
                    a,b:nod;
            end;
            new=record
                    x,y,jj,jl:extended;
                    kind,bh:longint;
            end;
    
    var
            i,j,k,l,n,m,q,zx,zd,ex,ey,sx,sy,ans,st,en,gs,head,tail,took:longint;
            spot:array[1..600] of new;
            f:array[1..600,1..600] of longint;
            x,y:array[1..600] of longint;
            a:array[1..100000] of longint;
            map,id,dl:array[0..600] of longint;
            bz:array[1..600] of boolean;
            op:array[0..600] of line;
            mid:extended;
    function vectorjia(a,b:nod):nod;
    var
            c:nod;
    begin
            c.x:=a.x+b.x;c.y:=a.y+b.y;
            exit(c);
    end;
    function vectorjian(a,b:nod):nod;
    var
            c:nod;
    begin
            c.x:=a.x-b.x;c.y:=a.y-b.y;
            exit(c);
    end;
    function vectorcheng(a:nod;b:real):nod;
    var
            c:nod;
    begin
            c.x:=a.x*b;c.y:=a.y*b;
            exit(c);
    end;
    function cross(a,b:nod):real;
    begin
            exit(a.x*b.y-a.y*b.x);
    end;
    function dist(a,b:point):real;
    begin
            exit(sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)));
    end;
    function dotji(a,b:nod):real;
    begin
            exit(a.x*b.x+a.y*b.y);
    end;
    procedure qsort(l,r:longint);
    var
            i,j:longint;
            m,m1:extended;
            k:new;
            o:extended;
    begin
            i:=l;j:=r;
            m:=spot[(l+r) div 2].jj;
            m1:=spot[(l+r) div 2].jl;
            repeat
                    while (spot[i].jj>m) or ((spot[i].jj=m) and (spot[i].jl<m1)) do inc(i);
                    while (spot[j].jj<m) or ((spot[j].jj=m) and (spot[j].jl>m1)) do dec(j);
                    if i<=j then
                    begin
                            k:=spot[i];spot[i]:=spot[j];spot[j]:=k;
                            op[0]:=op[i];op[i]:=op[j];op[j]:=op[0];
                            id[0]:=id[i];id[i]:=id[j];id[j]:=id[0];
                            inc(i);dec(j);
                    end;
            until i>j;
            if l<j then qsort(l,j);
            if r>i then qsort(i,r);
    end;
    procedure hpi(n:longint);
    var
            i,j,k,first,last:longint;
            miny,minx:extended;
            xian,q:array[0..50000] of line;
            p:array[0..50000] of point;
            jj:array[0..50000] of real;
            bz:array[1..10000] of boolean;
            ee:array[1..10000] of longint;
            pp:point;
            kk:nod;
    function onleft(l:line;p:point):boolean;
    var
            a:nod;
    begin
            a.x:=p.x-l.a.x;a.y:=p.y-l.a.y;
            if cross(l.b,a)>0 then exit(true) else
            exit(false);
    end;
    function getpoint(a,b:line):point;
    var
            c,aa:nod;
            t,p1,p2:real;
    begin
            c:=vectorjian(a.a,b.a);
            p1:=cross(b.b,c);
            p2:=cross(a.b,b.b);
            t:=p1/p2;
            aa:=vectorjia(a.a,vectorcheng(a.b,t));
            getpoint.x:=aa.x;
            getpoint.y:=aa.y;
    end;
    begin
            for i:=1 to n do
            begin
                    if (op[i].b.y=0) and (op[i].b.x>0) then spot[i].jj:=0 else
                    if (op[i].b.y=0) and (op[i].b.x<0) then spot[i].jj:=180 else
                    if (op[i].b.x=0) and (op[i].b.y>0) then spot[i].jj:=90 else
                    if (op[i].b.x=0) and (op[i].b.y<0) then spot[i].jj:=270 else
                    if op[i].b.y>0 then
                    begin
                            if op[i].b.x<0 then spot[i].jj:=arctan(op[i].b.y/op[i].b.x)*(180/pi)+180
                            else if op[i].b.x>0 then spot[i].jj:=arctan(op[i].b.y/op[i].b.x)*(180/pi);
                    end
                    else
                    if op[i].b.y<0 then
                    begin
                            if op[i].b.x<0 then spot[i].jj:=arctan(op[i].b.y/op[i].b.x)*(180/pi)+180
                            else if op[i].b.x>0 then spot[i].jj:=arctan(op[i].b.y/op[i].b.x)*(180/pi)+360;
                    end;
                    kk.x:=x[st]-spot[i].x;kk.y:=y[st]-spot[i].y;
                    spot[i].jl:=abs(cross(op[i].b,kk))/sqrt(sqr(op[i].a.x-op[i].b.x)+sqr(op[i].a.y-op[i].b.y));
            end;
            qsort(1,n);
            for i:=1 to n do
            begin
                    xian[i]:=op[i];
            end;
            fillchar(bz,sizeof(bz),true);
            for i:=2 to n do
            begin
                    if spot[i].jj=spot[i-1].jj then
                    begin
                            bz[i]:=false;
                    end;
            end;
            first:=1;last:=1;
            fillchar(q,sizeof(q),0);
            fillchar(p,sizeof(p),0);
            q[1]:=xian[1];
            ee[1]:=id[1];
            for i:=2 to n do
            begin
                    if not bz[i] then continue;
                    while (first<last) and (onleft(xian[i],p[last-1])) do dec(last);
                    while (first<last) and (onleft(xian[i],p[first])) do inc(first);
                    inc(last);
                    ee[last]:=id[i];
                    q[last]:=xian[i];
                    if cross(q[last].b,q[last-1].b)=0 then
                    begin
                            dec(last);
                            pp.x:=xian[i].a.x;pp.y:=xian[i].a.y;
                            if onleft(q[last],pp) then
                            begin
                                    q[last]:=xian[i];
                            end;
                    end;
                    if first<last then
                    begin
                            p[last-1]:=getpoint(q[last-1],q[last]);
                    end;
            end;
            while (first<last) and (onleft(q[first],p[last-1])) do dec(last);
    
            for i:=first to last do
            begin
                    if ee[i]=en then f[st,en]:=0
                    else
                    f[st,ee[i]]:=1;
            end;
    end;
    
    procedure bfs(dep:longint);
    var
            i,j,k,l:longint;
    begin
            for i:=1 to en do
            begin
                    //if not bz[i] then
                    begin
                            if map[i]>map[a[dep]]+f[a[dep],i] then
                            begin
                                    inc(took);
                                    a[took]:=i;
                                    bz[i]:=true;
                                    map[i]:=map[a[dep]]+f[a[dep],i];
                            end;
                    end;
            end;
    end;
    
    begin
            //assign(input,'0data.in');reset(input);
            readln(q);
            while q>0 do
            begin
                    q:=q-1;
                    readln(n);
                    readln(ex,ey,sx,sy);
                    for i:=1 to n do
                    begin
                            readln(x[i],y[i]);
                            spot[i].x:=x[i];
                            spot[i].y:=y[i];
                    end;
                    if n=0 then
                    begin
                            writeln(0);
                            continue;
                    end;
                    fillchar(f,sizeof(f),127 div 3);
                    zd:=f[1,1];
                    en:=n+1;
                    zx:=1;
                    for i:=1 to n do
                    begin
                            k:=0;
                            for j:=1 to n do
                            begin
                                    if i<>j then
                                    begin
                                            inc(k);
                                            spot[k].x:=x[j];
                                            spot[k].y:=y[j];
                                            op[k].b.x:=(y[j]-y[i])*10000;
                                            op[k].b.y:=-(x[j]-x[i])*10000;
                                            op[k].a.x:=(x[i]+x[j])/2-op[k].b.x;
                                            op[k].a.y:=(y[i]+y[j])/2-op[k].b.y;
                                            id[k]:=j;
                                    end;
                            end;
                            inc(k);spot[k].x:=0;spot[k].y:=0;op[k].b.x:=0;op[k].b.y:=ey;op[k].a.x:=0;op[k].a.y:=0;id[k]:=en;
                            inc(k);spot[k].x:=0;spot[k].y:=ey;op[k].b.x:=ex;op[k].b.y:=0;op[k].a.x:=0;op[k].a.y:=ey;id[k]:=en;
                            inc(k);spot[k].x:=ex;spot[k].y:=ey;op[k].b.x:=0;op[k].b.y:=-ey;op[k].a.x:=ex;op[k].a.y:=ey;id[k]:=en;
                            inc(k);spot[k].x:=ex;spot[k].y:=0;op[k].b.x:=-ex;op[k].b.y:=0;op[k].a.x:=ex;op[k].a.y:=0;id[k]:=en;
                            st:=i;
                            hpi(k);
                    end;
    
                    for i:=2 to n do
                    begin
                            if sqr(x[i]-sx)+sqr(y[i]-sy)<sqr(x[zx]-sx)+sqr(y[zx]-sy) then
                            zx:=i;
                    end;
    
                    head:=1;tail:=1;took:=1;
                    a[1]:=zx;
                    fillchar(bz,sizeof(bz),false);
                    fillchar(map,sizeof(map),127 div 3);
                    map[zx]:=1;
                    bz[zx]:=true;
                    repeat
                            for i:=head to tail do
                                    bfs(i);
                            head:=tail+1;
                            tail:=took;
                    until head>tail;
                    {
                    for i:=1 to en do
                    begin
                            for j:=1 to en do
                            begin
                                    if f[i,j]<zd then
                                    begin
                                            write(f[i,j],' ');
                                    end
                                    else
                                    write(0,' ');
                            end;
                            writeln;
                    end;
                    }
                    writeln(map[en]);
            end;
    end.
    end.
    
    
    
  • 相关阅读:
    PCM简介
    微波炉炖蛋
    python的命令行参数处理
    耳机标准
    SELinux杂谈
    Linux ssh服务器配置
    Centos 7安装nginx
    WPF TextBox属性IsReadOnlyCaretVisible
    [WPF打印]WPF 文档元素(Run TextBlock Paragraph)的文字对齐方式
    [SQLite3]connection string的连接池参数引发的错误
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148354.html
Copyright © 2011-2022 走看看