随笔-68  评论-10  文章-0  trackbacks-0
经典的压缩DP.
 
题目描述:
      Bugs公司生产一种2x3单位尺寸的高科技芯片,芯片被嵌入NxM的模板内。模板接受过严格的检查,损坏的单位小方格已被标上黑色记号。
      嵌入芯片的要求是,放置芯片的区域内不能有黑色记号,芯片间不能重叠。  求出可能的最大芯片数量。

 分析:     
       我们从左至右考虑每列的放置。由于芯片长度只有3,所以第j列芯片的放置只受第j-1和j-2列放置情况的影响。同时,如果方格(i,j-1)被黑色标记或其他芯片占据,方格(i,j-2)即使空闲对第j列也没影响。
      这里以0表示方格(i,j-2),(i,j-1)空闲; 以1表示方格(i,j-2)被占据,方格(i,j-1)空闲;以2表示方格(i,j-1)被占据。对于每一行有三种可能的状态。所以第j-2和j-1列的放置情况可以用m位的3进制表示。

状态转移方程推导:
      假如我们现在要放置第j列,那么它将受到前两列放置情况的影响。那么我们怎么来表示状态转移呢?
      令f[i][j]前j列放置好后,并且放置情况为i时芯片的最大数量。f[i][j]=max{f[k][j-1]+num}.  由此,第j列的放置可由前j-1列的放置情况来推导。

详细见代码:
#include<iostream>
using namespace std;
int n,m,t;
bool bug[12][155];
int f[60000][2];
int b[12],s[12];

void dfs(int j,int i,int cur,int sta,int num)
{
    
int tt,d;
    
if(cur>m)
    
{
        
if(f[sta][j&1]<f[i][(j-1)&1]+num)
            f[sta][j
&1]=f[i][(j-1)&1]+num;
        
return
    }

    
//当前位置不放芯片.
    if(bug[cur][j])  tt=2;
    
else if(s[cur]>0) tt=s[cur]-1;
    
else tt=0;
    d
=sta+tt*b[cur-1];
    dfs(j,i,cur
+1,d,num);
    
//横着放芯片.
    if(cur+1<=m&&s[cur]==0&&s[cur+1]==0&&!bug[cur][j]&&!bug[cur+1][j])
    
{
        d
=sta+2*b[cur-1]+2*b[cur];
        dfs(j,i,cur
+2,d,num+1);
    }

    
//竖着放芯片.
    if(cur+2<=m&&s[cur]<=1&&s[cur+1]<=1&&s[cur+2]<=1&&!bug[cur][j]&&!bug[cur+1][j]&&!bug[cur+2][j])
    
{
        d
=sta+2*b[cur-1]+2*b[cur]+2*b[cur+1];
        dfs(j,i,cur
+3,d,num+1);
    }

}


int main()
{
    
int i,j,k,v;
    b[
0]=1;
    
for(i=1;i<=10;i++)
        b[i]
=b[i-1]*3;
    scanf(
"%d",&t);
    
while(t--)
    
{
        
int x,y;
        scanf(
"%d%d%d",&n,&m,&k);
        memset(bug,
false,sizeof(bug));
        
for(i=0;i<k;i++)
        
{
            scanf(
"%d%d",&x,&y);
            bug[y][x]
=true;
        }

        memset(f,
-1,sizeof(f));
        f[b[m]
-1][0]=0;
        
for(j=1;j<=n;j++)
        
{
            
for(i=0;i<b[m];i++) f[i][j&1]=-1;
            
for(i=0;i<b[m];i++)
                
if(f[i][(j-1)&1]!=-1)
                
{
                    v
=i;
                    s[
0]=1;
                    
for(k=1;k<=m;k++)
                    
{
                        s[k]
=v%3;
                        v
/=3;
                    }

                    dfs(j,i,
1,0,0);
                }

        }

        
int ans=-1;
        
for(i=0;i<b[m];i++)
            
if(ans<f[i][n&1]) ans=f[i][n&1];
        printf(
"%d\n",ans);     
    }

    
return 0;
}

posted on 2010-08-15 13:09 wuxu 阅读(288) 评论(0)  编辑 收藏 引用 所属分类: 动态规划

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理