这是一道简单的搜索题,但是非常难想到(据说当年的这题,全国没有一个人完全做对)。
首相我们来分析下,由于题目说矩形不能相互重合,即不能相交,并且k<=4。 那么我们可以分别写出矩形的排列方式。
1、当k=1时,就是一个大矩形,求所有点的左上右下的两个点。
2、当k=2时,有如下两个排列方式
那么怎么计算呢?
对于左图,我们先将原先的点,按照y坐标升序排序,然后循环选择中间点,1i之间用一个矩形,i+1n再用一个矩形。
而右图,按x坐标升序排序,之后的操作一样
3、当k=3时,有如下六种方式:
有了对k=2的分析基础,我相信,k=n的dfs深搜应该不难,就是一遍遍画矩形画下去,注意剪枝就行了,我自己写的时候,由于一开始没有在dfs中穿数组,导致每一遍for都要用一个sort,导致最后一个点超时了,后来改了改才过的。
其实仔细想想挺简单的。
上代码:
#include
#define ull unsigned long long
using namespace std;
const int maxn=1e2+7;
int n,k,ans=0x7fffffff;
struct Node{
int x,y,id;
}node[maxn];
bool cmp(Node xx,Node yy){
if(xx.x==yy.x)
return xx.y<yy.y;
return xx.x<yy.x;
}
bool cmp1(Node xx,Node yy){
if(xx.y==yy.y)
return xx.x<yy.x;
return xx.y<yy.y;
}
void dfs(int ctk,int sum,int tp,Node n1[maxn],Node n2[maxn]){
if(ctk>k || sum>ans)
return;
if(tp>n){
if(ctk==k)
ans=min(sum,ans);
return;
}
int downx=0x7fffffff,downy=0x7fffffff,upx=-1,upy=-1;
sort(n1+tp,n2+1+n,cmp);
for(int i=tp;i<=n;i++){
downx=min(node[i].x,downx);
downy=min(node[i].y,downy);
upx=max(node[i].x,upx);
upy=max(node[i].y,upy);
dfs(ctk+1,sum+(upx-downx)*(upy-downy),i+1,n1,n2);
}
downx=0x7fffffff,downy=0x7fffffff,upx=-1,upy=-1;
sort(n2+tp,n2+n+1,cmp1);
for(int i=tp;i<=n;i++){
downx=min(node[i].x,downx);
downy=min(node[i].y,downy);
upx=max(node[i].x,upx);
upy=max(node[i].y,upy);
dfs(ctk+1,sum+(upx-downx)*(upy-downy),i+1,n1,n2);
}
}
int main(){
//freopen(".in","r",stdin);
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d %d",&node[i].x,&node[i].y);
node[i].id=i;
}
dfs(0,0,1,node,node);
printf("%d",ans);
return 0;
}
i].id=i;
}
dfs(0,0,1,node,node);
printf("%d",ans);
return 0;
}