现在的位置: 首页 > 综合 > 正文

vijos P1126矩形覆盖

2018年04月24日 ⁄ 综合 ⁄ 共 1472字 ⁄ 字号 评论关闭

描述

在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示。例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7)。

这些点可以用 k 个矩形(1<=k<=4)全部覆盖,矩形的边平行于坐标轴。当 k=2 时,可用如图二的两个矩形 s1,s2 覆盖,s1,s2 面积和为 4。问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢。约定:覆盖一个点的矩形面积为 0;覆盖平行于坐标轴直线上点的矩形面积也为0。各个矩形必须完全分开(边线与顶点也都不能重合)。

图片

格式

输入格式

格式为
n k
xl y1
x2 y2
... ...
xn yn (0<=xi,yi<=500)

输出格式

一个整数,即满足条件的最小的矩形面积之和。

样例1

样例输入1

4 2
1 1
2 2
3 6
0 7

样例输出1

4

题解

看着数据范围就是搜索了,这道题我用了三个剪枝(如果能算剪枝的话)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,ans=1<<30;
struct dian {int x,y;} a[52];
struct jux{int xz,xy,ys,yx,tag;} b[5];
void init()
{
	scanf("%d%d",&n,&m);
	int i;
	for(i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
}
bool jiao(jux i,int x,int y)
{
	if(x>=i.xz&&x<=i.xy&&y<=i.ys&&y>=i.yx) return true;
	else return false;
}
bool check(jux i,jux j)
{
	if(jiao(j,i.xz,i.yx)) return true;
	if(jiao(j,i.xy,i.yx)) return true;
	if(jiao(j,i.xz,i.ys)) return true;
	if(jiao(j,i.xy,i.ys)) return true;
	return false;
}
void dfs(int x)
{
	int i,j,s=0;
	for(i=1;i<=m;i++)//1、判断矩形是否重合 
	   {if(b[i].tag)
	       {s+=(b[i].xy-b[i].xz)*(b[i].ys-b[i].yx);
		    for(j=i+1;j<=m;j++)//节省时间 
		       {if(b[j].tag&&check(b[i],b[j])) return;}
		   }
	   }
	if(s>=ans) return; //2、一种常用剪枝 
	if(x>n) {ans=s; return;}
	jux t;
	for(i=1;i<=m;i++)
	   {t=b[i];
	    if(!b[i].tag)
	       {b[i].xz=a[x].x; b[i].xy=a[x].x; b[i].ys=a[x].y; b[i].yx=a[x].y;
		    b[i].tag=1;
		   }
	    else
	       {b[i].xz=min(a[x].x,b[i].xz); b[i].xy=max(b[i].xy,a[x].x);
		    b[i].ys=max(b[i].ys,a[x].y); b[i].yx=min(b[i].yx,a[x].y);
		   }
		dfs(x+1);
		b[i]=t;
		if(!t.tag) return;//3、保证每个矩形都用上 
	   }
}
int main()
{
	init(); dfs(1);
	printf("%d\n",ans);
	return 0;
}

抱歉!评论已关闭.