POJ 1038 状压DP

一个公司生产一种2*3规模的芯片,但是原材料上面有一些地方是不能用来当作芯片材料的,给出原料大小,及上面不能做原料的点,问你怎么分解,可以使生成芯片最大化。


对M进行三进制状压

last数组存储第i-1行和i-2行状态,cur数组存储i行和i-1行状态

cur[k]=2; // 本行k位置和上行k位置都不可用

cur[k]=1; // 本行k位置可用,上行k位置不可用

cur[k]=0; // 本行和上行位置k均可用


必须用滚动数组,否则爆内存


#include "stdio.h"
#include "string.h"

int b[20],ans,n,m;
int dp[2][69050],last[21],cur[21],map[160][160];

int updata(int i,int j)
{
    int res,k;
    res=0;
    memset(cur,0,sizeof(cur));
    memset(last,0,sizeof(last));

    for (k=1;k<=m;k++)
    {last[k]=j%3; j/=3;}

    for (k=1;k<=m;k++)
    if (map[i][k]==1)
    {
        cur[k]=2; // 本行k位置和上行k位置都不可用
        res+=b[k]*2;
    }else
    if (last[k]==2) // 上一行 k位置被占,上上行k位置没有被占
    {
        cur[k]=1; // 本行k位置可用,上行k位置不可用
        res+=b[k];
    }
    else
        cur[k]=0; // 本行和上行位置k均可用

    return res; // 本行位置压缩值
}

void dfs(int i,int now,int k,int status) // 第i行,价值为now,当前放第k个,状压值status
{
    int temp;
    if (now>ans) ans=now;
    if (now>dp[i][status]) dp[i][status]=now;
    if (k+1<=m && cur[k]==0 && cur[k+1]==0 && last[k]==0 && last[k+1]==0)  // 本行,上行,上上行的k和k+1位置均可用
    {
        cur[k]=2;
        cur[k+1]=2;
        temp=status+b[k]*2+b[k+1]*2;
        dfs(i,now+1,k+2,temp);
        cur[k]=0;
        cur[k+1]=0;
    }// 放置3行*2列 矩阵

    if (k+2<=m && cur[k]==0 && cur[k+1]==0 && cur[k+2]==0) // 本行,上行的k和k+1,k+2位置均可用
    {
        cur[k]=cur[k+1]=cur[k+2]=2;
        temp=status+b[k]*2+b[k+1]*2+b[k+2]*2;
        dfs(i,now+1,k+3,temp);
        cur[k]=cur[k+1]=cur[k+2]=0;
    } // 放置2行*3列 矩阵

    if (k+1<=m) dfs(i,now,k+1,status);
}
int main()
{
    int i,Case,k,aim,status,j,x,y;

    b[0]=0;
    b[1]=1;
    for (i=2;i<=11;i++)
        b[i]=b[i-1]*3;

    scanf("%d",&Case);
    while (Case--)
    {
        scanf("%d%d%d",&n,&m,&k);
        memset(map,0,sizeof(map));
        while (k--)
        {
            scanf("%d%d",&x,&y);
            map[x][y]=1;
        }
        aim=b[m+1]-1;
        status=0;
        for (i=1;i<=m;i++)
            if (map[1][i]==1) status+=2*b[i];
            else status+=b[i];

        memset(dp,-1,sizeof(dp));
        dp[1][status]=0;
        ans=0;
        for (i=2;i<=n;i++)
        {
            memset(dp[i%2],-1,sizeof(dp[i%2]));
            for (j=0;j<=aim;j++)
                if (dp[1-i%2][j]!=-1)
                {
                    status=updata(i,j);
                    dfs(i%2,dp[1-i%2][j],1,status);
                }
        }
        printf("%d\n",ans);



    }
    return 0;

}





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值