这个题目还是比较容易想到用状态dp来解的,但是状态的转移比较麻烦,并且加上有离散化,比较容易出错。
dp[i][j][k]表示覆盖前i列,用了j个矩形,当前覆盖状态为k的最优解。
k==1:覆盖1号格子
k==2:覆盖2号格子
k==3:覆盖1,2号格子,并且为同一个矩形
k==4:覆盖1,2号格子,并且为不同矩形
那么转移的时候就需要考虑,新建矩形,或者直接把当前矩形边长延伸。转移种类较多。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e3+9;
bool a[3][maxn];
int x[maxn],y[maxn],f[maxn],g[maxn];
int dp[maxn][maxn][5];
struct D
{
int id,key;
bool operator <(const D & xx) const
{
return key<xx.key;
}
}h[maxn];
int main()
{
// freopen("in.txt","r",stdin);
int n,K,b;
while(scanf("%d %d %d",&n,&K,&b)!=EOF)
{
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
{
scanf("%d %d",&x[i],&y[i]);
h[i].key=y[i],h[i].id=i;
}
sort(h+1,h+1+n);
int top=0;
f[h[1].id]=++top;
g[top]=h[1].key;
for(int i=2;i<=n;i++)
{
if(h[i].key!=h[i-1].key) ++top;
f[h[i].id]=top;
g[top]=h[i].key;
}
for(int i=1;i<=n;i++)
a[x[i]][f[i]]=1;
memset(dp,50,sizeof(dp));
dp[0][0][0]=0;
for(int k=0;k<top;k++)
{
for(int i=0;i<=K;i++)
for(int j=0;j<5;j++)
{
if(a[1][k+1]==0)
dp[k+1][i+1][2]=min(dp[k+1][i+1][2],dp[k][i][j]+1);
if(a[2][k+1]==0)
dp[k+1][i+1][1]=min(dp[k+1][i+1][1],dp[k][i][j]+1);
dp[k+1][i+1][3]=min(dp[k+1][i+1][3],dp[k][i][j]+2);
dp[k+1][i+2][4]=min(dp[k+1][i+2][4],dp[k][i][j]+2);
if(j==1)
{
if(a[2][k+1]==0)
dp[k+1][i][j]=min(dp[k+1][i][j],dp[k][i][j]+g[k+1]-g[k]);
else
dp[k+1][i+1][4]=min(dp[k+1][i+1][4],dp[k][i][j]+g[k+1]-g[k]+1);
}
else if(j==2)
{
if(a[1][k+1]==0)
dp[k+1][i][j]=min(dp[k+1][i][j],dp[k][i][j]+g[k+1]-g[k]);
else
dp[k+1][i+1][4]=min(dp[k+1][i+1][4],dp[k][i][j]+g[k+1]-g[k]+1);
}
else if(j==3)
{
dp[k+1][i][j]=min(dp[k+1][i][j],dp[k][i][j]+(g[k+1]-g[k])*2);
}
else if(j==4)
{
dp[k+1][i][j]=min(dp[k+1][i][j],dp[k][i][j]+(g[k+1]-g[k])*2);
if(a[2][k+1]==0)
dp[k+1][i][1]=min(dp[k+1][i][1],dp[k][i][j]+g[k+1]-g[k]);
else
dp[k+1][i+1][4]=min(dp[k+1][i+1][4],dp[k][i][j]+g[k+1]-g[k]+1);
if(a[1][k+1]==0)
dp[k+1][i][2]=min(dp[k+1][i][2],dp[k][i][j]+g[k+1]-g[k]);
else
dp[k+1][i+1][4]=min(dp[k+1][i+1][4],dp[k][i][j]+g[k+1]-g[k]+1);
}
}
}
int ans=1e9;
for(int k=0;k<=K;k++)
for(int i=0;i<5;i++)
ans=min(ans,dp[top][k][i]+K-k);
cout<<ans<<endl;
}
return 0;
}