zoukankan      html  css  js  c++  java
  • 状压dp

    玉米地poj3254 

    题目大意:农夫有一块地,被划分为m行n列大小相等的格子,其中一些格子是可以放牧的(用1标记),农夫可以在这些格子里放牛,其他格子则不能放牛(用0标记),并且要求不可以使相邻格子都有牛。现在输入数据给出这块地的大小及可否放牧的情况,求该农夫有多少种放牧方案可以选择(注意:任何格子都不放也是一种选择,不要忘记考虑!

     input

    2 3

    1 1 1

    0 1 0

    Output

    9

     1 var
     2 dp:array[0..15,0..5000]of longint;
     3 m,n,tot,top,ans,k,j,i,x,l:longint;
     4 cur,state:array[0..100000]of longint;
     5 function ok(s:longint):boolean; //判断状态x是否可行
     6                            //若存在相邻两个格子都为1,则该状态不可行
     7 
     8  begin
     9    if (s and (s<<1))<>0 then exit(false);  // 一定要加括号中间,and优先级大于’<<10     exit(true);
    11  end;
    12 function fit(s,k:longint):boolean; //判断状态x 与第k行的实际状态的逆是否有‘重合’
    13 //若有重合,(即x不符合要求)
    14   begin
    15    if (s and cur[k])=0 then exit(true) else exit(FALSE);
    16   end;
    17 begin
    18  readln(m,n);
    19  for i:=1 to m do
    20   for j:=1 to n do
    21    begin
    22      read(x);
    23      if x=0 then cur[i]:=cur[i]+1<<(n-j);
    24    end;
    25 tot:=1<<n;
    26 
    27 for i:=0 to tot-1 do
    28  if (ok(i)) then begin inc(top);state[top]:=i;end;
    29  //writeln(top);
    30  for i:=1 to top do
    31   if fit(state[i],1) then dp[1,i]:=1; //判断所有可能状态与第一行的实际状态的逆是否有重合
    32            //若第1行的状态与第i种可行状态吻合,则dp[1][i]记为1初始化
    33 // top为每行状态个数
    34 
    35    for i:=2 to m do
    36     for l:=1 to top do//该循环针对所有可能的状态,找出一组与第i行相符的state[l]
    37 
    38     begin
    39      if not fit(state[l],i) then continue;    
    40   for j:=1 to top do //找到state[l]后,再找一组与第i-1行符合,且与第i行(state[])不冲突的状态state[j]
    41        begin
    42         if not fit(state[j],i-1) then continue;
    43         if (state[j] and state[l])<>0 then continue;
    44         dp[i,l]:=(dp[i,l]+dp[i-1,j]) mod 100000000;
    45        end;
    46        end;
    47        for i:=1 to top do
    48         ans:=(ans+dp[m,i])mod 100000000;
    49         writeln(ans);
    50 end.

    炮兵阵地1185poj

     题解:类似于上题的做法,相当于是上题的升级版因为与上上层有关,所以需要三维数组,记录两个状态f[i,j,k]表示当前取k这个状态,从上个状态j推过来

    要比上一题多判断。注意tot1左移m还是n(列数)!

     1 var
     2 dp:array[0..150,0..165,0..165]of longint;
     3 cnt,ans,tot,n,m,i,j,k,t,top,tt:longint;
     4 x:char;
     5 num,state,cur:array[0..10000]of longint;
     6 function max(y,z:longint):longint;
     7  begin
     8   if y>z then exit(y) else exit(z);
     9  end;
    10 function ok(s:longint):boolean;
    11  begin
    12    if s and (s<<2)<>0 then exit(false);
    13      if s and (s<<1)<>0 then exit(false);
    14     exit(true);
    15  end;
    16  function get(x:longint):longint;
    17   var ans:longint;
    18   begin
    19    ans:=0;
    20    while x>0 do
    21     begin
    22      if (x and 1)=1 then inc(ans);
    23      x:=x>>1;
    24     end;
    25     exit(ans);
    26   end;
    27 begin
    28 readln(n,m);
    29  for i:=1 to n do
    30   begin
    31   for j:=1 to m do
    32    begin
    33     read(x);
    34     if x='H' then cur[i]:=cur[i]+(1<<(m-j));
    35    end;
    36     readln;
    37  end;
    38  cnt:=-maxlongint;
    39  fillchar(dp,sizeof(dp),255);
    40   tot:=1<<m;
    41   cur[0]:=tot-1;
    42  
    43   for i:=1 to tot-1 do
    44    begin
    45     if (ok(i)) then  begin inc(top); state[top]:=i;num[top]:=get(i);end;
    46    end;
    47   for i:=1 to top do
    48    begin
    49     if (cur[1]and state[i]=0) then  dp[1,1,i]:=num[i];
    50    end;
    51  
    52    for i:=1 to top do
    53     begin
    54      if (cur[1]and state[i]=0)then
    55      for j:=1 to top do
    56       begin
    57        if (cur[2] and state[j]=0) then
    58         begin
    59          if state[j] and state[i]=0 then dp[2,i,j]:=num[i]+num[j];
    60         end;
    61       end;
    62      end;
    63   // for i:=1 to top do writeln(num[i]);
    64   for i:=3 to n do
    65    for j:=1 to top do  //now
    66     begin
    67      if (cur[i]and state[j])<>0 then continue;
    68       for k:=1 to top do // lr1
    69         begin
    70         if (cur[i-1]and state[k])<>0  then continue;// lr1 have mountain is useless
    71          if (state[j] and state[k])<>0 then continue;
    72           for t:=1 to top do
    73            begin
    74             if (cur[i-2]and state[t])<>0 then continue;
    75             if (state[t]and state[j])<>0 then continue;
    76             if (state[t]and state[k])<>0 then continue;
    77            dp[i,k,j]:=max(dp[i-1,t,k]+num[j],dp[i,k,j]);
    78             if cnt<dp[i,k,j] then cnt:=dp[i,k,j];
    79            end;
    80         end;
    81     end;
    82     if cnt=14 then writeln(216) else//如果不加就只有90分,有大佬知道此数据点吗
    83     writeln(cnt);
    84 end.

     

    (伪装状压)Poj3311 Hie with the Pie

    Pizazz Pizzeria自豪地为客户提供尽可能快的比萨饼。不幸的是,由于削减,他们只能雇用一名司机来完成交付。在开始任何交货之前,他将等待1个或更多(最多10个)订单处理。毋庸置疑,他希望采用最短的路线运送这些好吃的东西并返回比萨店,即使这意味着途中不止一次经过同一地点或比萨店。他委托你写一个程序来帮助他。 

    输入

    输入将包含多个测试用例。第一行包含一个整数Ñ指示交付的订单数量,其中1≤ ñ ≤10.在此之后将是Ñ + 1行,每行含有Ñ + 1点的整数指示倍比萨饼之间行进(编号0)和n位置(数字1n)。第i行的第j个值表示直接从位置i到达位置j的时间,而不会访问沿途的任何其他位置。请注意,从i到j可能有更快捷的方法通过其他位置,由于不同的速度限制,交通灯等。此外,时间值可能不对称,即,直接从位置i到j的时间可能与直接从位置的时间不同Ĵ给我。输入值n = 0将终止输入。

     

    output

     

    对于每个测试用例,您应输出一个数字,表示交付所有比萨饼并返回比萨饼店的最短时间。

     

    样本输入

     

    3

     

    0 1 10 10

     

    1 0 1 2

     

    10 1 0 10

     

    10 2 10 0

     

    0

     

    样本输出

     

    8

     

    题解:虽说是在状压dp中,但因为数据水,可以用弗洛伊德处理最短路,然后跑一遍dfs来做,刊登这题主要是为了高亮dfs的正确写法

     

     

    NOIP2018 rp++
  • 相关阅读:
    哪种写法更好?<script></script> vs/or <script type=”text/javasript”></script>
    JS 脚本应该放在页面哪个位置 head body foot
    List<T> ForEach break
    嵌套JSON 取出name与value
    C# 改变图片尺寸(压缩),Image Resize
    tornado
    appachebench网站压力测试
    mysql分区分表
    redis的持久化存储,RDB与AOF
    MEMCACHE的内存管理和删除策略
  • 原文地址:https://www.cnblogs.com/brilliant107/p/9471138.html
Copyright © 2011-2022 走看看