P1034 [NOIP 2002 提高组] 矩形覆盖
题目描述
在平面上有 n 个点,每个点用一对整数坐标表示。例如:当 n=4 时,4 个点的坐标分别为:p1(1,1),p2(2,2),p3(3,6),p4(0,7),见图一。
这些点可以用 k 个矩形全部覆盖,矩形的边平行于坐标轴。当 k=2 时,可用如图二的两个矩形 s1,s2 覆盖,s1,s2 面积和为 4。问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢?
约定:覆盖一个点的矩形面积为 0;覆盖平行于坐标轴直线上点的矩形面积也为 0。各个矩形必须完全分开(边线与顶点也都不能重合)。
输入格式
第一行共两个整数 n,k,含义如题面所示。
接下来 n 行,其中第 i+1 行有两个整数 xi,yi,表示平面上第 i 个点的坐标。
输出格式
共一行一个整数,为满足条件的最小的矩形面积之和。
输入输出样例
输入 #1
4 2
1 1
2 2
3 6
0 7
输出 #1
4
说明/提示
对于 100% 数据,满足 1≤n≤50,1≤k≤4,0≤xi,yi≤500。
【题目来源】
NOIP 2002 提高组第四题
利用两次排序,分别以x,y来排序,每一个点可以分别和它的下面,左面进行dp,寻求最佳答案(上面和右面可以通过后面的点来比较),最后求最小值即可。
参考代码:
#include<bits/stdc++.h>
#define int long long
int const N=55;
using namespace std;
int num[N][N],dp[N][8],n,k;
struct node{
int x,y;
bool friend operator <(node aa,node bb)
{
if(aa.x!=bb.x)
return aa.x<bb.x;
else return aa.y<bb.y;
}
bool friend operator >(node aa,node bb)
{
if(aa.y!=bb.y)
return aa.y<bb.y;
else return aa.x<bb.x;
}
}w[N];
bool cmp(node a,node b)
{
return a<b;
}
bool cmp1(node a,node b)
{
return a>b;
}
int chang(int l,int r)
{
int minx=0x7fffffff,miny=0x7fffffff,maxx=0,maxy=0;
for(int i=l;i<=r;i++)
{
minx=min(minx,w[i].x);
miny=min(miny,w[i].y);
maxy=max(maxy,w[i].y);
maxx=max(maxx,w[i].x);
}
return (maxx-minx)*(maxy-miny);
}
void yu()
{
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
num[i][j]=chang(i,j);
}
int qiu()
{
yu();
dp[1][1]=0;
for(int i=2;i<=n;i++)
{
dp[i][1]=num[1][i];
for(int r=2;r<=k;r++)
for(int j=2;j<i;j++)
dp[i][r]=min(dp[i][r],dp[j][r-1]+num[j+1][i]);
}
return dp[n][k];
}
signed main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>k;
int maxx=0x7fffffff;
for(int i=1;i<=n;i++)
cin>>w[i].x>>w[i].y;
memset(dp,0x3f,sizeof(dp));
sort(w+1,w+1+n,cmp);
maxx=min(maxx,qiu());
memset(dp,0x3f,sizeof(dp));
sort(w+1,w+1+n,cmp1);
maxx=min(maxx,qiu());
cout<<maxx;
return 0;
}