题目链接:http://poj.org/problem?id=2430
题目大意及思路:用最多k个矩形覆盖所有的牛,且要使总面积最小,做法是将两行压缩成一行并进行离散化,对于每一列有四种状态,而在dp的时候也有四种状态,1、只覆盖上面,2、只覆盖下面,3、上下用一个矩形覆盖,4、上下用两个矩形覆盖。这样就可以写出转移方程了。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define Max 110
int max(int a,int b)
{
return a>b?a:b;
}
inline int min(int a,int b)
{
return a<b?a:b;
}
int pos[1010],n,k,b;
int s[1010],dp[1010][1010][4];
struct node
{
int x,y;
bool operator<(const node b)const
{
if(y==b.y)
return x<b.x;
return y<b.y;
}
}a[1010];
int main()
{
int i,j,l,cnt;
while(scanf("%d%d%d",&n,&k,&b)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
}
cnt=1;
sort(a+1,a+n+1);
memset(s,0,sizeof(s));
pos[cnt]=a[1].y;
if(a[1].x==1)
s[cnt]=0;
else
s[cnt]=1;
for(i=2;i<=n;i++)
{
if(a[i].y==a[i-1].y)
{
s[cnt]=2;
continue;
}
cnt++;
pos[cnt]=a[i].y;
if(a[i].x==1)
s[cnt]=0;
else
s[cnt]=1;
}
// for(i=1;i<=cnt;i++)
// printf("i %d s %d\n",i,s[i]);
// pos[0]=pos[1]-1;
for(i=0;i<=cnt;i++)
for(j=0;j<=k;j++)
for(l=0;l<4;l++)
dp[i][j][l]=inf;
dp[0][0][2]=0;
for(i=1;i<=cnt;i++)
{
for(j=1;j<=k;j++)
{
int tmp2;
int tmp=min(min(dp[i-1][j-1][0],dp[i-1][j-1][1]),min(dp[i-1][j-1][2],dp[i-1][j-1][3]));
if(j>=2)
tmp2=min(min(dp[i-1][j-2][0],dp[i-1][j-2][1]),min(dp[i-1][j-2][2],dp[i-1][j-2][3]));
if(s[i]==0)
{
dp[i][j][0]=min(tmp+1,min(dp[i-1][j][0],dp[i-1][j][3])+pos[i]-pos[i-1]);
dp[i][j][2]=min(tmp+2,dp[i-1][j][2]+(pos[i]-pos[i-1])*2);
dp[i][j][3]=min(dp[i-1][j][3]+2*(pos[i]-pos[i-1]),min(dp[i-1][j-1][0],dp[i-1][j-1][1])+pos[i]-pos[i-1]+1);
if(j>=2)
dp[i][j][3]=min(tmp2+2,dp[i][j][3]);
}
else if(s[i]==1)
{
dp[i][j][1]=min(tmp+1,min(dp[i-1][j][1],dp[i-1][j][3])+pos[i]-pos[i-1]);
dp[i][j][2]=min(tmp+2,dp[i-1][j][2]+(pos[i]-pos[i-1])*2);
dp[i][j][3]=min(dp[i-1][j][3]+2*(pos[i]-pos[i-1]),min(dp[i-1][j-1][0],dp[i-1][j-1][1])+pos[i]-pos[i-1]+1);
if(j>=2)
dp[i][j][3]=min(tmp2+2,dp[i][j][3]);
}
else
{
dp[i][j][2]=min(tmp+2,dp[i-1][j][2]+(pos[i]-pos[i-1])*2);
dp[i][j][3]=min(dp[i-1][j][3]+2*(pos[i]-pos[i-1]),min(dp[i-1][j-1][0],dp[i-1][j-1][1])+pos[i]-pos[i-1]+1);
if(j>=2)
dp[i][j][3]=min(tmp2+2,dp[i][j][3]);
}
// for(l=0;l<4;l++)
// printf("i %d j %d l %d dp %d\n",i,j,l,dp[i][j][l]);
}
}
int ans=inf;
for(j=0;j<4;j++)
{
ans=min(ans,dp[cnt][k][j]);
}
printf("%d\n",ans);
}
}