hdu 2442 Bricks

首先感谢ACdreaam 的爱神。。。。

题意:用俄罗斯方块求完美覆盖,那些方块放置方法不变。

方法:三进制状态压缩,比二进制快可很多。

虽然有神代码参考,可是还是WA了很久,,,,

#include<stdio.h>
#include<string.h>
int dp[105][729],pow[10],stac1[10],stac2[10];
int n,m,ans;
int max(int a,int b)
{
    return a>b?a:b;
}
void work()
{
    pow[0]=1;
    for(int i=1;i<10;i++)
    pow[i]=3*pow[i-1];
}
int ctod(int three[10]){
    int state=0;
    for(int i=0;i<m;i++)
        state+=three[i]*pow[i];
    return state;
}
void dtoc(int state,int three[10]){//就是这了,状态翻译时,即使数字变量为0也要记录下去直到满了为止,0也是有意义的!!!!!!!
    for(int i=0;i<m;i++,state/=3)
        three[i]=state%3;
}
void init()
{
    memset(dp,-1,sizeof(dp));
    for(int i=0;i<m;i++)
     {
         stac1[i]=1;
         stac2[i]=0;
     }
     dp[0][ctod(stac1)]=0;
}
void dfs(int i,int idx,int num){
    if(idx>=m){
        int j=ctod(stac1);
      dp[i][j]=max(dp[i][j],num);
        return ;
    }
    if(idx+1<m&&stac1[idx]==0&&stac1[idx+1]==0&&stac2[idx+1]==0){
        stac1[idx+1]=2;stac1[idx]=1;
        dfs(i,idx+2,num+4);
        stac1[idx+1]=stac1[idx]=0;
    }
    if(idx+2<m&&stac1[idx]==0&&stac1[idx+1]==0&&stac1[idx+2]==0&&stac2[idx+1]==0){
        stac1[idx]=stac1[idx+2]=1;stac1[idx+1]=2;
        dfs(i,idx+2,num+5);
        stac1[idx]=stac1[idx+2]=stac1[idx+1]=0;
    }
    if(idx+2<m&&stac1[idx]==0&&stac1[idx+1]==0&&stac1[idx+2]==0){
        stac1[idx]=stac1[idx+2]=1;stac1[idx+1]=2;
        dfs(i,idx+2,num+4);
        stac1[idx]=stac1[idx+2]=stac1[idx+1]=0;
    }
    if(idx+2<m&&stac1[idx]==0&&stac1[idx+1]==0&&stac1[idx+2]==0){
        stac1[idx]=stac1[idx+1]=1;stac1[idx+2]=2;
        dfs(i,idx+2,num+4);
        stac1[idx]=stac1[idx+2]=stac1[idx+1]=0;
    }
    if(idx+1<m&&stac1[idx+1]==0&&stac2[idx]==0&&stac2[idx+1]==0){
        stac1[idx+1]=2;
        dfs(i,idx+2,num+4);
        stac1[idx+1]=0;
    }
    dfs(i,idx+1,num);
}
int main()
{
    int i,t,k,j;
    work();
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(m>n)
        {
            t=m;
            m=n;
            n=t;
        }
        init();
        ans=0;
        for(i=1;i<=n-1;i++)
          for(j=0;j<pow[m];j++)
              if(dp[i-1][j]!=-1)
            {
                dtoc(j,stac2);
                for(k=0;k<m;k++)
                stac1[k]=max(0,stac2[k]-1);
                dfs(i,0,dp[i-1][j]);
            }
            ans=0;
            for(i=0;i<pow[m];i++)
            ans=max(ans,dp[n-1][i]);
          printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值