成都手机网站建设开发郑州网站设计
题目描述
在平面上有 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;
}