• 一类预估未来的动态规划


    参考论文《对一类动态规划问题的研究》

    《多角度思考创造性思维——运用树型动态规划解题的思路和方法探析》

    这类动态规划的特点就是当前的决策会影响未来“行动”的费用,而我们并不能记录每个的所有决策

    这时候我们就考虑在当前状态对未来状态预估,从而提前计算当前决策对未来影响的费用

    下面的几道题目都很好,并且都能在这两篇论文中找到详细的题解,这里就贴代码不再赘述了

    bzoj1812

    不错的树dp,处理x为根子树的时候,我们预估x的某个祖先有伐木场时子树内的运费

    详见《多角度思考创造性思维——运用树型动态规划解题的思路和方法探析》

      1 const inf=2147483647;
      2 type node=record
      3        po,next,num:longint;
      4      end;
      5 
      6 var e:array[0..210] of node;
      7     w,fa,p,d,g:array[0..110] of longint;
      8     f:array[0..110,0..110,0..110] of longint;
      9     i,j,k,len,x,y,n,m:longint;
     10 
     11 procedure add(x,y,z:longint);
     12   begin
     13     inc(len);
     14     e[len].po:=y;
     15     e[len].num:=z;
     16     e[len].next:=p[x];
     17     p[x]:=len;
     18   end;
     19 
     20 function min(a,b:longint):longint;
     21   begin
     22     if a>b then exit(b) else exit(a);
     23   end;
     24 
     25 procedure dfs(x:longint);
     26   var i,y,z,mi:longint;
     27   begin
     28     if p[x]=0 then
     29     begin
     30       i:=fa[x];
     31       while i>-1 do
     32       begin
     33         f[x,i,0]:=(d[x]-d[i])*w[x];
     34         i:=fa[i];
     35       end;
     36       f[x,x,1]:=0;
     37       exit;
     38     end;
     39     i:=p[x];
     40     while i<>0 do
     41     begin
     42       y:=e[i].po;
     43       d[y]:=d[x]+e[i].num;
     44       dfs(y);
     45       i:=e[i].next;
     46     end;
     47     i:=p[x];
     48     while i<>0 do
     49     begin
     50       y:=e[i].po;
     51       z:=x;
     52       while z>-1 do
     53       begin
     54         for j:=m downto 0 do
     55         begin
     56           mi:=inf;
     57           for k:=0 to j do
     58             mi:=min(mi,f[x,z,k]+f[y,z,j-k]);
     59           f[x,z,j]:=mi;
     60         end;
     61         z:=fa[z];
     62       end;
     63       i:=e[i].next;
     64     end;
     65     z:=fa[x];
     66     while z>-1 do
     67     begin
     68       for i:=0 to m do
     69         if f[x,z,i]<inf then f[x,z,i]:=f[x,z,i]+(d[x]-d[z])*w[x];
     70       z:=fa[z];
     71     end;
     72     fillchar(g,sizeof(g),0);
     73     i:=p[x];
     74     while i<>0 do
     75     begin
     76       y:=e[i].po;
     77       for j:=m downto 0 do
     78       begin
     79         mi:=inf;
     80         for k:=1 to j do
     81           mi:=min(mi,g[k]+f[y,x,j-k]);
     82         g[j]:=mi;
     83       end;
     84       i:=e[i].next;
     85     end;
     86     z:=x;
     87     while z>-1 do
     88     begin
     89       for i:=0 to m do
     90         f[x,z,i]:=min(f[x,z,i],g[i]);
     91       z:=fa[z];
     92     end;
     93   end;
     94 
     95 begin
     96   readln(n,m);
     97   for i:=1 to n do
     98   begin
     99     readln(w[i],fa[i],y);
    100     add(fa[i],i,y);
    101   end;
    102   fa[0]:=-1;
    103   dfs(0);
    104   writeln(f[0,0,m]);
    105 end.
    View Code

    bzoj1495

    非常好的树dp,处理x为根子树的时候,预估x的祖先AB付费方式的大小情况从而计算影响

    具体请见《多角度思考创造性思维——运用树型动态规划解题的思路和方法探析》

    其中转换计算方式,对状态的压缩以及复杂度的分析都非常有价值,建议认真研究

     1 const inf=1000000007;
     2 var a,f:array[0..2050,0..2050] of longint;
     3     d,b,c:array[0..2050] of longint;
     4     n,m,x,y,i,j,k,p,l,r,ans:longint;
     5 
     6 function min(a,b:longint):longint;
     7   begin
     8     if a>b then exit(b) else exit(a);
     9   end;
    10 
    11 function lca(a,b:longint):longint;
    12   begin
    13     while a<>b do
    14     begin
    15       if a>b then a:=a div 2
    16       else b:=b div 2;
    17     end;
    18     exit(a);
    19   end;
    20 
    21 begin
    22   readln(n);
    23   m:=1 shl n;
    24   for i:=1 to m do
    25     read(b[i]);
    26   for i:=1 to m do
    27     read(c[i]);
    28   for i:=2 to m*2-1 do
    29     d[i]:=d[i div 2]+1;
    30   readln;
    31   for i:=1 to m-1 do
    32   begin
    33     for j:=i+1 to m do
    34     begin
    35       read(y);
    36       x:=d[lca(i+m-1,j+m-1)];
    37       inc(a[i,x],y);
    38       inc(a[j,x],y);
    39     end;
    40     readln;
    41   end;
    42   for i:=m to m*2-1 do
    43   begin
    44     x:=i-m+1;
    45     for j:=0 to m-1 do
    46     begin
    47       f[i,j shl 1+b[x]]:=c[x];
    48       for k:=0 to n-1 do
    49       begin
    50         if (j and (1 shl k)>0) then y:=1 else y:=0;
    51         inc(f[i,j shl 1+1-y],a[x,k]);
    52       end;
    53     end;
    54   end;
    55   for i:=1 to m-1 do
    56     for j:=0 to m*2-1 do
    57       f[i,j]:=inf;
    58 
    59   for i:=m-1 downto 1 do
    60     for j:=0 to 1 shl d[i]-1 do
    61       for k:=0 to 1 shl (n-d[i]) do
    62       begin
    63         x:=j shl (n-d[i]+1) or k;
    64         if k<1 shl (n-d[i])-k then y:=0 else y:=1;
    65         for p:=0 to min(k,1 shl (n-d[i]-1)) do
    66         begin
    67           if k-p>1 shl (n-d[i]-1) then continue;
    68           l:=((j+y*(1 shl d[i])) shl (n-d[i]))+p;
    69           r:=((j+y*(1 shl d[i])) shl (n-d[i]))+(k-p);
    70           f[i,x]:=min(f[i,x],f[i*2,l]+f[i*2+1,r]);
    71         end;
    72       end;
    73 
    74   ans:=f[1,0];
    75   for i:=1 to m*2-1 do
    76     ans:=min(ans,f[1,i]);
    77 
    78   writeln(ans);
    79 end.
    View Code

    bzoj1065

    也是非常好的树dp,可以看《对一类动态规划问题的研究》,讲解的很详细

    在做树dp的时候预估当前子树的跟x距1的深度所带来的影响(因为x的祖先的后继可能被修改连到1)

     1 var f:array[0..70,0..70,0..70] of double;
     2     g,c,b:array[0..70] of double;
     3     p:array[0..70] of longint;
     4     j,tmp,i,n,m,len:longint;
     5     ans:double;
     6 
     7 function max(a,b:double):double;
     8   begin
     9     if a>b then exit(a) else exit(b);
    10   end;
    11 
    12 function min(a,b:longint):longint;
    13   begin
    14     if a>b then exit(b) else exit(a);
    15   end;
    16 
    17 procedure dfs(x,d:longint);
    18   var i,j,k,l:longint;
    19   begin
    20     for i:=2 to n do
    21       if p[i]=x then dfs(i,d+1);
    22     for l:=min(2,d) to d do
    23     begin
    24       for i:=2 to n do
    25         if p[i]=x then
    26         begin
    27           for j:=m downto 0 do //树上背包注意转移顺序
    28             for k:=j downto 0 do
    29               f[x,j,l]:=max(f[x,j,l],f[x,k,l]+max(f[i,j-k,l+1],f[i,j-k,1]));
    30         end;
    31       for j:=0 to m do
    32         f[x,j,l]:=f[x,j,l]+c[x]*b[l];
    33     end;
    34     if d>1 then
    35     begin
    36       fillchar(g,sizeof(g),0);
    37       for i:=2 to n do
    38         if p[i]=x then
    39         begin
    40           for j:=m downto 0 do
    41             for k:=j downto 0 do
    42               g[j]:=max(g[j],g[k]+max(f[i,j-k,1],f[i,j-k,2]));
    43         end;
    44       for j:=1 to m do
    45         f[x,j,1]:=g[j-1]+c[x]*b[1];
    46     end;
    47   end;
    48 
    49 function dp:double;
    50   var i,j,k:longint;
    51   begin
    52     fillchar(g,sizeof(g),0);
    53     for i:=2 to n do
    54       if p[i]=1 then
    55       begin
    56         for j:=m downto 0 do
    57           for k:=j downto 0 do
    58             g[j]:=max(g[j],g[k]+f[i,j-k,1]);
    59       end;
    60     dp:=0;
    61     for i:=0 to m-1 do
    62       dp:=max(dp,g[i]);
    63     if tmp=1 then dp:=max(dp,g[m]);  //原来后继就是1就不用修改
    64   end;
    65 
    66 begin
    67   readln(n,m,b[1]);
    68   for i:=2 to n do
    69     b[i]:=b[i-1]*b[1];
    70   for i:=1 to n do
    71     read(p[i]);
    72   for i:=1 to n do
    73     read(c[i]);
    74   len:=2;
    75   i:=p[1];
    76   while i<>1 do  //穷举环长
    77   begin
    78     fillchar(f,sizeof(f),0);
    79     tmp:=p[i];
    80     p[i]:=1;
    81     for j:=2 to n do
    82       if p[j]=1 then dfs(j,1);
    83     ans:=max(ans,(dp+c[1])/(1-b[len]));
    84     p[i]:=tmp;
    85     i:=p[i];
    86     inc(len);
    87   end;
    88   writeln(ans:0:2);
    89 end.
    View Code

    bzoj2037

    相对简单,这题不用新开状态,直接在当前状态加上对未来的影响即可

    详见《对一类动态规划问题的研究》

     1 var f:array[0..1010,0..1010,1..2] of longint;
     2     w:array[0..1010,0..1010] of longint;
     3     s,a,b,v:array[0..1010] of longint;
     4     i,j,l,n,x0:longint;
     5 
     6 procedure swap(var a,b:longint);
     7   var c:longint;
     8   begin
     9     c:=a;
    10     a:=b;
    11     b:=c;
    12   end;
    13 
    14 procedure sort(l,r:longint);
    15   var i,j,x:longint;
    16   begin
    17     i:=l;
    18     j:=r;
    19     x:=a[(l+r) shr 1];
    20     repeat
    21       while a[i]<x do inc(i);
    22       while x<a[j] do dec(j);
    23       if not(i>j) then
    24       begin
    25         swap(a[i],a[j]);
    26         swap(b[i],b[j]);
    27         swap(v[i],v[j]);
    28         inc(i);
    29         dec(j);
    30       end;
    31     until i>j;
    32     if l<j then sort(l,j);
    33     if i<r then sort(i,r);
    34   end;
    35 
    36 function max(a,b:longint):longint;
    37   begin
    38     if a>b then exit(a) else exit(b);
    39   end;
    40 
    41 function cost(a,b:longint):longint;
    42   begin
    43     exit(a*b);
    44   end;
    45 
    46 begin
    47   readln(n,x0);
    48   for i:=1 to n do
    49     read(a[i]);
    50   for i:=1 to n do
    51     read(b[i]);
    52   for i:=1 to n do
    53     read(v[i]);
    54   sort(1,n);
    55   for i:=1 to n do
    56     s[i]:=s[i-1]+v[i];
    57   for i:=1 to n do
    58     for j:=i to n do
    59       w[i,j]:=s[n]-(s[j]-s[i-1]);
    60   for i:=1 to n do
    61   begin
    62     f[i,i,1]:=b[i]-cost(abs(a[i]-x0),s[n]);
    63     f[i,i,2]:=f[i,i,1];
    64   end;
    65   for l:=2 to n do
    66     for i:=1 to n-l+1 do
    67     begin
    68       j:=i+l-1;
    69       f[i,j,1]:=b[i]+max(f[i+1,j,1]-cost(a[i+1]-a[i],w[i+1,j]),f[i+1,j,2]-cost(a[j]-a[i],w[i+1,j]));
    70       f[i,j,2]:=b[j]+max(f[i,j-1,2]-cost(a[j]-a[j-1],w[i,j-1]),f[i,j-1,1]-cost(a[j]-a[i],w[i,j-1]));
    71     end;
    72   writeln(max(f[1,n,1],f[1,n,2])/1000:0:3);
    73 end.
    View Code

    poj1390

    区间dp,对于消去区间[i,j],我们预估后面会连接k个和区域j同色的方块来计算分数

    详见《对一类动态规划问题的研究》

     1 var f:array[0..201,0..201,0..201] of longint;
     2     wh:array[0..201,0..201] of longint;
     3     len,color,s,loc,a,maxl,sc:array[0..201] of longint;
     4     l,w,i,j,k,r,t,n,q,p:longint;
     5 
     6 function max(a,b:longint):longint;
     7    begin
     8      if a>b then exit(a) else exit(b);
     9    end;
    10 
    11 begin
    12   readln(t);
    13   for w:=1 to t do
    14   begin
    15     readln(r);
    16     n:=0;
    17     fillchar(s,sizeof(s),0);
    18     fillchar(len,sizeof(len),0);
    19     for i:=1 to r do
    20     begin
    21       read(a[i]);
    22       if a[i]=a[i-1] then
    23         inc(len[n])
    24       else begin
    25         inc(n);
    26         inc(s[a[i]]);
    27         loc[n]:=s[a[i]];
    28         wh[a[i],s[a[i]]]:=n;
    29         len[n]:=1;
    30         color[n]:=a[i];
    31       end;
    32     end;
    33     fillchar(sc,sizeof(sc),0);
    34     for i:=n downto 1 do
    35     begin
    36       maxl[i]:=sc[color[i]];
    37       inc(sc[color[i]],len[i]);
    38     end;
    39     fillchar(f,sizeof(f),0);
    40     for i:=1 to n do
    41       for k:=0 to maxl[i] do
    42         f[i,i,k]:=sqr(len[i]+k);
    43     for l:=1 to n-1 do
    44       for i:=1 to n-l do
    45       begin
    46         j:=i+l;
    47         for k:=0 to maxl[j] do
    48         begin
    49           f[i,j,k]:=f[i,j-1,0]+sqr(len[j]+k);
    50           q:=loc[j]-1;
    51           while q>0 do
    52           begin
    53             p:=wh[color[j],q];
    54             if p<i then break;
    55             f[i,j,k]:=max(f[i,j,k],f[i,p,k+len[j]]+f[p+1,j-1,0]);
    56             dec(q);
    57           end;
    58         end;
    59       end;
    60     writeln('Case ',w,': ',f[1,n,0]);
    61   end;
    62 end.
    View Code
  • 相关阅读:
    poj 3278 catch that cow
    POJ 1028 Web Navigation
    poj 2643 election
    hdu 1908 double queues
    hdu_2669 Romantic(扩展欧几里得)
    0/1背包 dp学习~6
    校验码
    最长上升子序列(LIS经典变型) dp学习~5
    LCS最长公共子序列~dp学习~4
    最长上升子序列(LIS) dp学习~3
  • 原文地址:https://www.cnblogs.com/phile/p/4665057.html
Copyright © 2020-2023  润新知