POJ 2430 状压DP

题意:
这里写图片描述
这里写图片描述
思路:
先预处理出所有格子的statement
statement=1–>只有上边的格子被覆盖
statement=2–>只有下边的格子被覆盖
statement=3–>上下都被覆盖

f[i][j][k]表示状态为i时,前j个地方的奶牛,盖k座房子 最少盖住的格子

i有四种情况

  • i=1代表只有上边的格子被覆盖
  • i=2代表只有下边的格子被覆盖
  • i=3代表上下被同一个房子覆盖
  • i=4代表上下被不同房子覆盖

    状态转移很麻烦 特别麻烦

  • statement=1时

f[1][j][k]=min(min(f[1][j-1][k-1],min(f[2][j-1][k-1],min(f[3][j-1][k-1],f[4][j-1][k-1])))+1,f[1][j-1][k]+node[j].pos-node[j-1].pos);
f[1][j][k]=min(f[1][j][k],f[4][j-1][k]+node[j].pos-node[j-1].pos);
f[3][j][k]=min(temp+2,f[3][j-1][k]+2*(node[j].pos-node[j-1].pos));
f[4][j][k]=f[4][j-1][k]+2*(node[j].pos-node[j-1].pos);
f[4][j][k]=min(f[4][j][k],f[1][j-1][k-1]+node[j].pos-node[j-1].pos+1);
f[4][j][k]=min(f[4][j][k],f[2][j-1][k-1]+node[j].pos-node[j-1].pos+1);

  • statement=2时同理
  • statement=3时

int temp=min(f[1][j-1][k-1],min(f[2][j-1][k-1],min(f[3][j-1][k-1],f[4][j-1][k-1])));
f[3][j][k]=min(temp+2,f[3][j-1][k]+2*(node[j].pos-node[j-1].pos));
if(k>1)f[4][j][k]=min(f[1][j-1][k-2],min(f[2][j-1][k-2],min(f[3][j-1][k-2],f[4][j-1][k-2])))+2;
f[4][j][k]=min(f[4][j][k],f[4][j-1][k]+2*(node[j].pos-node[j-1].pos));
f[4][j][k]=min(f[4][j][k],f[1][j-1][k-1]+node[j].pos-node[j-1].pos+1);
f[4][j][k]=min(f[4][j][k],f[2][j-1][k-1]+node[j].pos-node[j-1].pos+1);

最后代码如下:

//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,K,b,cnt,f[5][1005][1005];
struct Node{int sta,pos;}node[1005];
bool cmp(Node a,Node b){
    return a.pos<b.pos;
}
int main(){
    scanf("%d%d%d",&n,&K,&b);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&node[i].sta,&node[i].pos);
    sort(node+1,node+1+n,cmp);
    for(int i=1;i<=n;i++){
        if(node[i].pos==node[i-1].pos)
            node[cnt].sta=3;
        else node[++cnt]=node[i];
    }
    node[0].pos=node[1].pos;
    memset(f,0x3f,sizeof(f));
    f[1][0][1]=f[2][0][1]=1,f[3][0][1]=f[4][0][2]=2;
    for(int i=1;i<=4;i++){
        for(int j=1;j<=cnt;j++){
            for(int k=K;k;k--){
                if(node[j].sta==1){
                    int temp=min(f[1][j-1][k-1],min(f[2][j-1][k-1],min(f[3][j-1][k-1],f[4][j-1][k-1])));
                    f[1][j][k]=min(temp+1,f[1][j-1][k]+node[j].pos-node[j-1].pos);
                    f[1][j][k]=min(f[1][j][k],f[4][j-1][k]+node[j].pos-node[j-1].pos);
                    f[3][j][k]=min(temp+2,f[3][j-1][k]+2*(node[j].pos-node[j-1].pos));
                    f[4][j][k]=f[4][j-1][k]+2*(node[j].pos-node[j-1].pos);
                    f[4][j][k]=min(f[4][j][k],f[1][j-1][k-1]+node[j].pos-node[j-1].pos+1);
                    f[4][j][k]=min(f[4][j][k],f[2][j-1][k-1]+node[j].pos-node[j-1].pos+1);
                }
                else if(node[j].sta==2){
                    int temp=min(f[1][j-1][k-1],min(f[2][j-1][k-1],min(f[3][j-1][k-1],f[4][j-1][k-1])));
                    f[2][j][k]=min(temp+1,f[2][j-1][k]+node[j].pos-node[j-1].pos);
                    f[2][j][k]=min(f[2][j][k],f[4][j-1][k]+node[j].pos-node[j-1].pos);
                    f[3][j][k]=min(temp+2,f[3][j-1][k]+2*(node[j].pos-node[j-1].pos));
                    f[4][j][k]=f[4][j-1][k]+2*(node[j].pos-node[j-1].pos);
                    f[4][j][k]=min(f[4][j][k],f[1][j-1][k-1]+node[j].pos-node[j-1].pos+1);
                    f[4][j][k]=min(f[4][j][k],f[2][j-1][k-1]+node[j].pos-node[j-1].pos+1);
                }
                else{
                    int temp=min(f[1][j-1][k-1],min(f[2][j-1][k-1],min(f[3][j-1][k-1],f[4][j-1][k-1])));
                    f[3][j][k]=min(temp+2,f[3][j-1][k]+2*(node[j].pos-node[j-1].pos));
                    if(k>1)f[4][j][k]=min(f[1][j-1][k-2],min(f[2][j-1][k-2],min(f[3][j-1][k-2],f[4][j-1][k-2])))+2;
                    f[4][j][k]=min(f[4][j][k],f[4][j-1][k]+2*(node[j].pos-node[j-1].pos));
                    f[4][j][k]=min(f[4][j][k],f[1][j-1][k-1]+node[j].pos-node[j-1].pos+1);
                    f[4][j][k]=min(f[4][j][k],f[2][j-1][k-1]+node[j].pos-node[j-1].pos+1);
                }
            }
        }
    }
    for(int i=1;i<=4;i++)f[1][cnt][K]=min(f[1][cnt][K],f[i][cnt][K]);
    printf("%d\n",f[1][cnt][K]);
}

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值