【BZOJ1226】学校食堂Dining(状压DP)

题意:见题面

思路:设dp[i,sta,k]为前i个人已经吃完,从第i人到第i+b[i]人的吃饭状况是sta,前一个吃完的人离i的距离是k(可能为负)的最小值

[ dp[i+1,sta>>1,k-1]=min(dp[i+1,sta>>1,k-1],dp[i,sta,k]) (sta and 1=1,如果i已经吃完)]

[dp[i,sta+1<<l,l]=min(dp[i,sta+1<<l,l],dp[i,sta,k]+w(i+k,i+l) (第i+l人吃,前一个吃的人是i+k)]

[w(i,j)=b[i]  or  b[j]-b[i]  and  b[j]=b[i]  xor  b[j]]

注意转移的时候边界判断,是否超过l人里面最小的容忍范围

 1 const oo=2000000000;
 2 var dp:array[1..1100,0..300,-8..8]of longint;
 3     t,b:array[1..1100]of longint;
 4     cas,v,n,i,j,k,l,ans,r:longint;
 5 
 6 function clac(x,y:longint):longint;
 7 begin
 8  if x=0 then exit(0);
 9  exit(t[x] xor t[y]);
10 end;
11 
12 function min(x,y:longint):longint;
13 begin
14  if x<y then exit(x);
15  exit(y);
16 end;
17 
18 begin
19  assign(input,'bzoj1226.in'); reset(input);
20  assign(output,'bzoj1226.out'); rewrite(output);
21  readln(cas);
22  for v:=1 to cas do
23  begin
24   read(n);
25   for i:=1 to n do read(t[i],b[i]);
26   fillchar(dp,sizeof(dp),$7f);
27   dp[1,0,-1]:=0;
28   for i:=1 to n do
29    for j:=0 to (1<<8)-1 do
30     for k:=-8 to 7 do
31      if dp[i,j,k]<oo then
32      begin
33       if j and 1>0 then
34        dp[i+1,j>>1,k-1]:=min(dp[i+1,j>>1,k-1],dp[i,j,k])
35         else
36         begin
37          r:=oo;
38          for l:=0 to 7 do
39           if j and (1<<l)=0 then
40           begin
41            if i+l>r then break;
42            r:=min(r,i+b[i+l]+l);
43            dp[i,j+(1<<l),l]:=min(dp[i,j+(1<<l),l],dp[i,j,k]+clac(i+k,i+l));
44           end;
45         end;
46      end;
47   ans:=oo;
48   for i:=-8 to -1 do ans:=min(ans,dp[n+1,0,i]);
49   writeln(ans);
50  end;
51  close(input);
52  close(output);
53 end.
原文地址:https://www.cnblogs.com/myx12345/p/6208958.html