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

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.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值