zoukankan      html  css  js  c++  java
  • 【DP+ShortPath】[Dota1000]德鲁伊(Dyrad)

    时间限制:10000ms 内存限制:100000kB
    描述
    德鲁伊带着他的精灵熊在前线作战……
    德鲁伊打到了钱,会让他的熊宝宝回家买东西
    德鲁伊在1号点,家在M号点,中间有e条无向边,通过每一条边都有一个时间,德鲁伊会让他的熊宝宝买N次东西,熊宝宝会选一条路来回家,但是这些点有限制,每一个点在一定的次数内不能通过,所以,熊宝宝有时候会更换路径。
    德鲁伊可以让他的熊宝宝瞬间到他身边,所以熊宝宝买完东西回来不需要时间。
    熊宝宝的路径是德鲁伊想的,所以每次熊宝宝更换路径都要耗费K的时间(第一次想的路径不花时间)
    现在,德鲁伊想知道,买N次东西最少所需要的总时间是多少?
    输入
    第一行,四个数N,M,K,e
    接下来e行,每行三个数s,t,len,表示s到t有一条无向边,通过时间为len
    下面一行有一个数T,表示有T条限制
    接下来T行,每行三个数x,l,r,表示在l次到r次不能通过x
    输出
    一个数,表示最短总时间
    样例输入
    5 5 10 8
    1 2 1
    1 3 3
    1 4 2
    2 3 2
    2 4 4
    3 4 1
    3 5 2
    4 5 2
    4
    2 2 3
    3 1 1 
    3 3 3
    4 4 5
    样例输出
    32
    提示
    N<=10000,M<=10,K<=5000
    T<=100

    【Solution Of Loogint】

    本题是浙江省选的一道水题的变形,这道题是一道较简单的动态规划。

    F[i]表示到第i次所需要的最少时间

    F[i]←min{F[j]+SPFA(j+1,i)*(i-j)+k}(0<=j<=i-1)

    最后结果是F[n]-k

    方程中的SPFA表示的是从j+1天到i天不改变方案所能取得的最短路径长度,这个只要对SPFA中的vis数组进行一定的预处理即可。

    但魂之挽歌那个魂淡把n从100加强到了10000,O(n^2)的程序就跑得很吃力了…

    【Code 1: Tle】

      1: Program Dryad(input,output);
    
      2:   type point=^node;
    
      3:        node=record
    
      4:          data,weight:longint;
    
      5:          next:point;
    
      6:   end;
    
      7:   var que:array[1..2000]of longint;
    
      8:       vis,forbid:array[1..20]of boolean;
    
      9:       dist:array[1..20]of longint;
    
     10:       limit:array[1..100,0..100]of longint;
    
     11:       map:array[1..20]of point;
    
     12:       F:array[0..100]of longint;
    
     13:       i,j,n,m,k,e,x,y,len,t,w,l,r:longint;
    
     14:       p:point;
    
     15:   Function SPFA(l,r:longint):longint;
    
     16:     var i,j,head,tail,quehead:Longint;edge:point;
    
     17:     begin
    
     18:       fillchar(que,sizeof(que),0);
    
     19:       fillchar(vis,sizeof(vis),false);
    
     20:       for i:=1 to m do dist[i]:=19940805;
    
     21:       fillchar(forbid,sizeof(forbid),false);
    
     22:       for i:=l to r do
    
     23:         for j:=1 to limit[i,0] do
    
     24:           forbid[limit[i,j]]:=true;
    
     25:       dist[1]:=0;vis[1]:=true;
    
     26:       head:=0;tail:=1;
    
     27:       que[tail]:=1;
    
     28:       while head<tail do
    
     29:         begin
    
     30:           inc(head);
    
     31:           quehead:=que[head];
    
     32:           vis[quehead]:=false;
    
     33:           edge:=map[quehead];
    
     34:           while edge<>nil do
    
     35:             begin
    
     36:               if not forbid[edge^.data] then
    
     37:                 if dist[quehead]+edge^.weight<dist[edge^.data] then
    
     38:                   begin
    
     39:                     dist[edge^.data]:=dist[quehead]+edge^.weight;
    
     40:                     if not(vis[edge^.data]) then
    
     41:                       begin
    
     42:                         inc(tail);
    
     43:                         que[tail]:=edge^.data;
    
     44:                         vis[edge^.data]:=true;
    
     45:                       end;
    
     46:                   end;
    
     47:               edge:=edge^.next;
    
     48:             end;
    
     49:         end;
    
     50:       exit(dist[m]);
    
     51:     end;
    
     52:   begin
    
     53:     readln(n,m,k,e);
    
     54:     for i:=1 to e do
    
     55:       begin
    
     56:         readln(x,y,len);
    
     57:         new(p);p^.data:=y;p^.weight:=len;p^.next:=map[x];map[x]:=p;
    
     58:         new(p);p^.data:=x;p^.weight:=len;p^.next:=map[y];map[y]:=p;
    
     59:       end;
    
     60:     readln(t);
    
     61:     for i:=1 to t do
    
     62:       begin
    
     63:         readln(x,l,r);
    
     64:         for j:=l to r do
    
     65:           begin
    
     66:             inc(limit[j,0]);
    
     67:             limit[j,limit[j,0]]:=x;
    
     68:           end;
    
     69:       end;
    
     70:     for i:=1 to n do
    
     71:       begin
    
     72:         F[i]:=maxlongint;
    
     73:         for j:=0 to i-1 do
    
     74:           begin
    
     75:             w:=SPFA(j+1,i);
    
     76:             if w=19940805 then continue;
    
     77:             if F[i]>F[j]+w*(i-j)+k then
    
     78:               F[i]:=F[j]+w*(i-j)+k;
    
     79:           end;
    
     80:       end;
    
     81:     writeln(F[n]-k);
    
     82:   end.

    {

    This Code is Accepted at ZJOI2006_Trans.

    http://www.zybbs.org/JudgeOnline/problem.php?id=1003

    /**************************************************************

    Problem: 1003

    User: Loongint

    Language: Pascal

    Result: Accepted

    Time:68 ms

    Memory:304 kb

    ****************************************************************/

    }

    【Solution of Loongint】

    注意到原题的数据范围:天数是100,而节点数是20。Dyrad这个题的数据:次数10000,节点只有10。

    所以我们变换一下动归的方式。

    先DFS处理出所有的路径,然后把每一条路径看成一个体积1,价值为其路径长度和的物品,那么就成为了一个背包问题,总体积为次数n。

    F[i,j]表示到第i次且前一次所选择的路径为j所能获得的最短路程。

    F[i,j]←min{F[i-1,j]+value[j],F[i-1,l]+value[l]+k}//j and l is legal in this time.

    结果从F[n,i](1=<i<=MaxNumOfPath)中找即可。

    效率是O(n*MaxNumPath)的。

    代码不给了…因为Dsqwwe说,这样也超时,路径条数太多。

    【Solution ③ of Loongint】

    暴打魂之挽歌一顿…..(那家伙的代码ms是O(n)的….,马萨卡是贪心?)

  • 相关阅读:
    创建包含前后255天所有天数的视图。
    VC获取主机名和主机信息
    在PowerDesigner增加unique约束
    差集的几种计算方法
    动态列的处理(统计)。
    一个查询语句各个部分的执行顺序
    IDC机房跳线
    软件下载链接
    IDC装机检查思路
    运维工程师之IDC系列
  • 原文地址:https://www.cnblogs.com/Loongint/p/2193553.html
Copyright © 2011-2022 走看看