题意:给出 n*m(n ≤150,m≤10 ) 的棋盘,要在上面放置 2*3 的骨牌,有一些方格无法放置,求最多能放置多少个。
分析:因为每一行的状态都会影响到前两行,所以就用三进制的数记录第i行和第i-1行的状态。f[i,j]表示第i行和第i-1行状态为j时的最大放置数,然后暴力转移就好了。
黑书138已经写的很清楚了,这里就不多说了。
代码:
const maxn=59048; var t,l,i,j,k,n,m,p,ans,x,y,g:longint; v1,v2:array[1..150,1..10] of boolean; a:array[1..20] of longint; f:array[0..1,0..maxn] of longint; function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end; procedure work(x,s,num:longint); begin if x>m+1 then exit; if x=m+1 then begin f[g,s]:=num; exit; end; work(x+1,s*3,num); if v2[1,x] then work(x+3,s*27+26,num+1); end; procedure dfs(x,s,num:longint); begin if x>m+1 then exit; if x=m+1 then begin if f[1-g,j]+num>f[g,s] then begin f[g,s]:=f[1-g,j]+num; if f[g,s]>ans then ans:=f[g,s]; end; exit; end; dfs(x+1,s*3+max(a[x]-1,0),num); if (v1[i-2,x])and(a[x]=0)and(a[x+1]=0) then dfs(x+2,s*9+8,num+1); if (v2[i-1,x])and(a[x]<2)and(a[x+1]<2)and(a[x+2]<2) then dfs(x+3,s*27+26,num+1); end; begin readln(t); for l:=1 to t do begin readln(n,m,p); fillchar(v1,sizeof(v1),true); fillchar(v2,sizeof(v2),true); for i:=1 to p do begin readln(x,y); for j:=max(x-2,1) to x do for k:=max(y-1,1) to y do v1[j,k]:=false; for j:=max(x-1,1) to x do for k:=max(y-2,1) to y do v2[j,k]:=false; end; g:=0; for i:=0 to maxn do f[g,i]:=-1; work(1,0,0); ans:=0; for i:=3 to n do begin g:=1-g; for j:=0 to maxn do f[g,j]:=-1; for j:=0 to maxn do if f[1-g,j]>-1 then begin x:=j; for k:=m downto 1 do begin a[k]:=x mod 3; x:=x div 3; end; dfs(1,0,0); end; end; writeln(ans); end; end.