解题报告 Lights

Lights

【题目描述】

Spray来到了zz城。这个城市的的交通规则非常奇怪,城市公路通过路口相连,两个不同路口之间最多只有一条直达公路。公路的起止点不会是同一路口。在任意一条公路上顺不同方向走所需时间相同。每一个路口都有交通灯,这些交通灯在某一时刻要么是蓝色,要么是紫色。同一个灯上2个颜色的维持时间受到定期调控,总是蓝色持续一段时间,紫色持续一段时间。交通规则规定两个路口可以通车仅当公路两边交通灯的颜色相同(也就是说只要你在A路口看见A与B的交通灯颜色相同,那么就可以走上A-B这条路并到达B路口)。交通工具可以在路口等候。

现在Spray有这个城市的地图,包含:

·1.  通过所有公路需要的时间(整数)

·2.  每个路口交通灯两种颜色的持续时间(整数)

·3.  每个路口交通灯的初始颜色以及初始颜色的持续时间(整数). 

    你的任务是帮Spray找到一条从起点到终点的最快路径(保证路径唯一)。【输入数据】

第一行包含两个整数: 起点和终点的编号. 

第二行包含两个整数: N, M. (2 ≤ N ≤ 300 ,1 ≤ M ≤ 14000)

接下来 N 行描述 N 个路口的情况. 

第i+2行 是 i 号路口的信息: Ci, riC, tiB, tiP 。

其中字符 Ci 要么是“B”代表蓝色,要么是“P”代表紫色,表示 i 的起始颜色. riC, tiB, tiP 分别表示初始颜色,蓝色,紫色的持续时间, 

(1 ≤ tiC ≤ 100 . 1 ≤ riC ≤ tiC )

最后的 M 行表示关于 M 条公路的信息。包含: i, j, lij 。i 和 j 号路口被这条路连接. lij 是通过i到j这条公路需要的时间。(1 ≤ lij ≤ 100)

【输出数据】

如果存在最短路径:

第一行输出最短时间。

第二行是一个对应第一行答案的路口编号表,从起点到终点输出路口编号,数字之间用空格隔开(即输出路径方案)。
如果不存在,直接输出“0”。

【样例输入】

1 4
4 5
B 2 16 99
P 6 32 13
P 2 87 4
P 38 96 49
1 2 4
1 3 40
2 3 75
2 4 76
3 4 77

【样例输出】

127
1 2 4

 

 

 

四维 SPFA 

好理解,不好打。

 

注意 ci 是初始颜色还需要维持的时间。

 

 

 

program lonely;

  const

    maxn=10000;

    man=1000000000;

  type

    rec=record

      t:array[0..1] of longint;

      st,tst:longint;

    end;

    nod=record

      y,len,next:longint;

    end;

  var

    a:array[0..400] of rec;

    map:array[0..30000] of nod;

    first:array[0..400] of longint;

    f,dist:array[0..400] of longint;

    v:array[0..400] of boolean;

    tot,extra,st,en,head,tail,x,y,len,t,i,n,m:longint;

    c:char;

    que:array[0..10000] of longint;

  function min(a,b:longint):longint;

    begin

      if a<b then exit(a) else exit(b);

    end;

  function can(x,y,time:longint):boolean;

    var

      ta,tb,tta,ttb:longint;

    begin

      if (time<a[x].tst)and(time<a[y].tst) then

        begin

          if a[x].st=a[y].st then exit(true);

          ta:=a[x].tst-time;

          tb:=a[y].tst-time;

          if ta=tb then

            begin

              if a[x].t[1-a[x].st]=a[y].t[1-a[y].st] then

                begin

                  if a[x].t[a[x].st]=a[y].t[a[y].st] then

                    extra:=1000000000

                  else extra:=min(a[x].t[a[x].st],a[y].t[a[y].st])+ta+a[x].t[1-a[x].st];

                end

              else extra:=min(a[x].t[1-a[x].st],a[y].t[1-a[y].st])+ta;

            end

          else extra:=min(ta,tb);

          exit(false);

        end;

      if (time>=a[x].tst)and(time<a[y].tst) then

        begin

          ta:=(time-a[x].tst) mod (a[x].t[1]+a[x].t[0]);

          if (ta>a[x].t[1-a[x].st]) then

            begin

              if a[x].st=a[y].st then exit(true)

                else

                  begin

                    ta:=a[x].t[1]+a[x].t[0]-ta;

                    tb:=a[y].tst-time;

                    if ta=tb then

                      begin

                        if a[x].t[1-a[x].st]=a[y].t[1-a[y].st] then

                          begin

                            if a[x].t[a[x].st]=a[y].t[a[y].st] then

                              extra:=1000000000

                            else extra:=min(a[x].t[a[x].st],a[y].t[a[y].st])+ta+a[x].t[1-a[x].st];

                          end

                        else extra:=min(a[x].t[1-a[x].st],a[y].t[1-a[y].st])+ta;

                      end

                    else extra:=min(ta,tb);

                    exit(false);

                  end;

            end

          else

            begin

              if 1-a[x].st=a[y].st then exit(true)

                else

                  begin

                    ta:=a[x].t[1-a[x].st]-ta;

                    tb:=a[y].tst-time;

                    if ta=tb then

                      begin

                        if a[x].t[a[x].st]=a[y].t[1-a[y].st] then

                          begin

                            if a[x].t[1-a[x].st]=a[y].t[a[y].st] then

                              extra:=1000000000

                            else extra:=min(a[x].t[1-a[x].st],a[y].t[a[y].st])+ta+a[x].t[a[x].st];

                          end

                        else extra:=min(a[x].t[a[x].st],a[y].t[1-a[y].st])+ta;

                      end

                    else extra:=min(ta,tb);

                    exit(false);

                  end;

            end;

        end;

      if (time>=a[x].tst)and(time>=a[y].tst) then

        begin

          ta:=(time-a[x].tst) mod (a[x].t[1]+a[x].t[0]);

          tb:=(time-a[y].tst) mod (a[y].t[1]+a[y].t[0]);

          if (ta>a[x].t[1-a[x].st]) then

            begin

              ta:=a[x].t[1]+a[x].t[0]-ta;

              tta:=a[x].st

            end

          else

            begin

              tta:=1-a[x].st;

              ta:=a[x].t[tta]-ta;

            end;

          if (tb>a[y].t[1-a[y].st]) then

            begin

              tb:=a[y].t[1]+a[y].t[0]-tb;

              ttb:=a[y].st

            end

          else

            begin

              ttb:=1-a[y].st;

              tb:=a[y].t[ttb]-tb;

            end;

          if tta=ttb then exit(true)

            else

              begin

                if ta=tb then

                  begin

                    if a[x].t[1-tta]=a[y].t[1-ttb] then

                      begin

                        if a[x].t[tta]=a[y].t[ttb] then

                          extra:=1000000000

                        else extra:=min(a[x].t[tta],a[y].t[ttb])+ta+a[x].t[1-tta];

                      end

                    else extra:=min(a[x].t[1-tta],a[y].t[1-ttb])+ta;

                  end

                else extra:=min(ta,tb);

                exit(false);

              end;

        end;

      exit(false);

    end;

  procedure print(x:longint);

    begin

      if x=0 then exit;

      print(f[x]);

      write(x,' ');

    end;

  begin

    assign(input,'lights.in');

    reset(input);

    assign(output,'lights.out');

    rewrite(output);

    readln(st,en);

    readln(n,m);

    fillchar(a,sizeof(a),255);

    for i:=1 to n do

      begin

        read(c);

        if c='P' then a[i].st:=0 else a[i].st:=1;

        read(c);

        readln(a[i].tst,a[i].t[1],a[i].t[0]);

      end;

    tot:=0;

    for i:=1 to m do

      begin

        readln(x,y,len);

        inc(tot);

        map[tot].y:=y;map[tot].len:=len;

        map[tot].next:=first[x];

        first[x]:=tot;

        inc(tot);

        map[tot].y:=x;map[tot].len:=len;

        map[tot].next:=first[y];

        first[y]:=tot;

      end;

    for i:=1 to n do dist[i]:=man;

    dist[st]:=0;

    f[st]:=0;

    v[st]:=true;

    head:=0;tail:=1;

    que[tail]:=st;

    while head<>tail do

      begin

        inc(head);

        if head>maxn then head:=1;

        x:=que[head];

        t:=first[x];

        while t<>0 do

          begin

            y:=map[t].y;

            extra:=0;

            if (can(x,y,dist[x]))or(can(y,x,dist[x])) then

              begin

                if dist[x]+map[t].len<dist[y] then

                  begin

                    dist[y]:=dist[x]+map[t].len;

                    f[y]:=x;

                    if not v[y] then

                      begin

                        v[y]:=true;

                        inc(tail);

                        if tail>maxn then tail:=1;

                        que[tail]:=y;

                      end;

                  end;

              end

            else if dist[x]+map[t].len+extra<dist[y] then

              begin

                dist[y]:=dist[x]+map[t].len+extra;

                f[y]:=x;

                if not v[y] then

                  begin

                    v[y]:=true;

                    inc(tail);

                    if tail>maxn then tail:=1;

                    que[tail]:=y;

                  end;

              end;

            t:=map[t].next;

          end;

        v[x]:=false;

      end;

    if dist[en]<man then

      begin

        writeln(dist[en]);

        print(f[en]);

        writeln(en);

      end

    else writeln(0);

    close(input);

    close(output);

  end.

原文地址:https://www.cnblogs.com/SueMiller/p/2226670.html