zoukankan      html  css  js  c++  java
  • 一类预估未来的动态规划

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

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

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

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

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

    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
  • 相关阅读:
    leetcode 18 4Sum
    leetcode 71 Simplify Path
    leetcode 10 Regular Expression Matching
    leetcode 30 Substring with Concatenation of All Words
    leetcode 355 Design Twitte
    leetcode LRU Cache
    leetcode 3Sum
    leetcode Letter Combinations of a Phone Number
    leetcode Remove Nth Node From End of List
    leetcode Valid Parentheses
  • 原文地址:https://www.cnblogs.com/phile/p/4665057.html
Copyright © 2011-2022 走看看