状压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++
原文地址:https://www.cnblogs.com/brilliant107/p/9471138.html