题意:见题面
思路:设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.
时间: 2024-10-18 10:40:54