您的位置:首页 > 其它

jozj. 3511. 【NOIP2013模拟11.5A组】cza的蛋糕(cake)

2017-07-14 19:43 375 查看
Description

cza特别喜欢吃海苔,怎么吃也吃不够。cza的生日到来时,他的父母给他买了许许多多的海苔和一个生日蛋糕。海苔是一个1*2或2*1的长方形,而蛋糕则是一个n*m的矩阵。蛋糕上有一些蜡烛占据了位置,其他地方都可以放海苔。cza的父母让cza把海苔尽可能多的放在蛋糕上,但是海苔不能够重叠放置。cza想把海苔留着自己以后慢慢吃,可又不敢违背父母,于是他决定放一少部分在蛋糕上。为了不使父母起疑,cza必须确保放置完海苔后,蛋糕上不存在1*2或2*1的空白以放置更多的海苔。cza想知道这样得花多少海苔,请帮助他求出满足这样放置所需的最少海苔数。

Input

输入的第一行是蛋糕的规模n和m(注意是n行m列)

接下来的n行每一行含m个字符。每个字符要么是”.”,表示空白;要么是”*”,表示蜡烛。

Output

输出文件只包含一个整数k,表示满足题目要求的最小海苔数。

Sample Input

3 3



.*.



Sample Output

3

Data Constraint

对于30%的数据N<=5,M<=5

对于100%的数据N<=70, M<=7

分析:一开始就想到了状压dp,m<=7,每行状态就2^7-1种。转移就很恶心了。

我们设f[i,s1,s2]表示,第i行状态s1,且s1已经填到不能再填,下一行状态s2时的最少需要多少个1*2的矩形,若s1还能填,那全部不填不就是最好吗。显然,对于下一个状态f[i+1,s3,s4]其实就把s2填满,形成状态s3,但又不得不考虑s3下一行的情况,因为竖放会影响到下一行的状态。对于一个s1,s2转移成s3,s4就有两种情况,第一种是把s2中2个连续的0都变为1,s4不变;第二种是把s2中第一个1变为0,但s4中对应位置的1也要变为0,如果s4对应位置是1则不合法。因为每一个0都有两种情况,所以应分别讨论,用dfs去更新就最好了,s4的初值显然是s4这一行的a[i]。a[i]指第i行的蜡烛情况,用二进制表示,如果第j位是1,这这个位置有蜡烛。初值就是f[0,2^m-1,a[1]]=0,第0行填满,第1行就是a[1]。答案就是f[n,s,0],显然s一定是填满的,不用考虑s的合法性。如果不合法这个值一定是inf。

代码:

var
i,j,n,m,x,k,s,l,inf,ans:longint;
a:array [1..71] of longint;
f:array [0..71,0..130,0..130] of longint;
ch:char;

function min(x,y:longint):longint;
begin
if x<y then exit(x)
else exit(y);
end;

procedure change(k,x,y,z,t:longint);
begin
if (k>0) and (x and (1 shl (k-1))=0) and (y and (1 shl (k-1))=0) then exit;
if (k>1) and (y and (1 shl (k-1))=0) and (y and (1 shl (k-2))=0) then exit;
if k=m then
begin
f[i,y,z]:=min(f[i,y,z],f[i-1,j,l]+t);
exit;
end;
change(k+1,x,y,z,t);
if (z and (1 shl k)=0) and (y and (1 shl k)=0) then
change(k+1,x,y or (1 shl k),z or (1 shl k),t+1);
if (k<m-1) and (y and (1 shl k)=0) and (y and (1 shl (k+1))=0) then
change(k+2,x,y or (1 shl k) or (1 shl (k+1)),z,t+1);
end;

begin
assign(input,'cake.in');
assign(output,'cake.out');
reset(input);
rewrite(output);
readln(n,m);
for i:=1 to n do
begin
x:=0;
for j:=1 to m do
begin
read(ch);
x:=x shl 1;
if ch='*' then x:=x+1;
end;
readln;
a[i]:=x;
end;
fillchar(f,sizeof(f),$7f);
inf:=f[1,1,1];
s:=1 shl m-1;
f[0,s,a[1]]:=0;
for i:=1 to n do
for j:=0 to s do
for l:=0 to s do
if f[i-1,j,l]<inf then change(0,j,l,a[i+1],0);
ans:=maxlongint;
for i:=0 to s do
ans:=min(ans,f[n,i,0]);
writeln(ans);
close(input);
close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: