这个题挺好想 转移好麻烦
F[I][J][1…4] 表示当前序列第i列放j块覆盖情况位1…4的最小面积
情况 1 只有上端覆盖
2 只有下端
3 上下由一块一起覆盖
4 上下由不同覆盖
(要先离散化)
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct node{
int l,x;
}a[N*2],b[N*2];
bool cmp(node i,node j){return i.x<j.x;
}
int f[N][N][5],n,m,k,tot,ans=INT_MAX;
int main()
{
n=read(),k=read(),m=read();
for(int i=1;i<=n;i++) a[i].l=read(),a[i].x=read();
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
if(a[i].x!=a[i-1].x)b[++tot]=a[i];
else b[tot].l=3;
memset(f,127/3,sizeof f);
if(b[1].l==1) f[1][1][1]=1;
else if(b[1].l==2) f[1][1][2]=1;
f[1][2][4]=2,f[1][1][3]=2;
for(int i=2;i<=tot;i++)
for(int j=1;j<=k;j++){
if(b[i].l==1) f[i][j][1]=min(f[i-1][j][1],f[i-1][j][4])+b[i].x-b[i-1].x;
if(b[i].l==2) f[i][j][2]=min(f[i-1][j][2],f[i-1][j][4])+b[i].x-b[i-1].x;
if(j!=1) f[i][j][4]=f[i-1][j][4]+2*(b[i].x-b[i-1].x);
f[i][j][3]=f[i-1][j][3]+2*(b[i].x-b[i-1].x);
if(j==1) continue;
int mi=min(min(f[i-1][j-1][1],f[i-1][j-1][2]),min(f[i-1][j-1][3],f[i-1][j-1][4]));
if(b[i].l==1)f[i][j][1]=min(f[i][j][1],mi+1);
if(b[i].l==2)f[i][j][2]=min(f[i][j][2],mi+1);
f[i][j][3]=min(f[i][j][3],mi+2);
mi=min(f[i-1][j-1][1],min(f[i-1][j-1][2],f[i-1][j-1][4]))+b[i].x+1-b[i-1].x;
f[i][j][4]=min(f[i][j][4],mi);
if(j==2) continue;
mi=min(min(f[i-1][j-2][1],f[i-1][j-2][2]),min(f[i-1][j-2][3],f[i-1][j-2][4]));
f[i][j][4]=min(f[i][j][4],mi+2);
}
for(int i=1;i<=k;i++)
for(int j=1;j<=4;j++)
ans=min(ans,f[tot][i][j]);
cout<<ans<<endl;
}