不想写题意描述了,看链接吧。。。
题目分析
由于数据范围较小( k < 5 , n < 50 k<5,n<50 k<5,n<50)所以考虑直接搜索,通过搜索来确定每个点是否能放进一个矩形中,状态记录当前点被矩形覆盖后的总面积.
程序实现
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
struct Node{
int x,y;
}node[55];
struct square{
int x1,y1,x3,y3;
}sqr[6];
int n,k,ans,tot,maxn=inf;
bool check(int now,int sq){//check函数用来检查该点放入该矩形是否合法
if(sqr[sq].x1 ==0&&sqr[sq].y1 ==0&&sqr[sq].x3 ==0&&sqr[sq].y3 ==0){
sqr[sq].x1 =sqr[sq].x3 =node[now].x ;
sqr[sq].y1 =sqr[sq].y3 =node[now].y ;
}//矩形赋初值
if(node[now].x <sqr[sq].x1 ) sqr[sq].x1 =node[now].x ;
if(node[now].y <sqr[sq].y1 ) sqr[sq].y1 =node[now].y ;
if(node[now].x >sqr[sq].x3 ) sqr[sq].x3 =node[now].x ;
if(node[now].y >sqr[sq].y3 ) sqr[sq].y3 =node[now].y ;//已有初值,矩形大小改变
for(int i=1;i<=k;i++){
if(i==sq)continue;
if(sqr[sq].x1 <=sqr[i].x3 &&sqr[sq].y1 <=sqr[i].y3 &&sqr[i].x3 <=sqr[sq].x3 &&sqr[i].y3 <=sqr[sq].y3 )return false;
if(sqr[sq].x1 <=sqr[i].x1 &&sqr[sq].y1 <=sqr[i].y1 &&sqr[i].x1 <=sqr[sq].x3 &&sqr[i].y1 <=sqr[sq].y3 )return false;
if(sqr[sq].y1 <=sqr[i].y1 &&sqr[i].y1 <=sqr[sq].y3 &&sqr[sq].x1 <=sqr[i].x1 &&sqr[i].x1 <=sqr[sq].x3 )return false;
if(sqr[sq].y1 <=sqr[i].y3 &&sqr[i].y3 <=sqr[sq].y3 &&sqr[sq].x1 <=sqr[i].x3 &&sqr[i].x3 <=sqr[sq].x3 )return false;//判断矩形重合(不包括点和边)
if(sqr[sq].x1 ==sqr[i].x1 &&sqr[sq].y1 ==sqr[i].y1 )return false;
if(sqr[sq].x3 ==sqr[i].x3 &&sqr[sq].y3 ==sqr[i].y3 )return false;
if(sqr[sq].x3 ==sqr[i].x1 &&sqr[sq].y1 ==sqr[i].y3 )return false;
if(sqr[sq].x1 ==sqr[i].x3 &&sqr[sq].y3 ==sqr[i].y1 )return false;//没写这个特判就只剩80了,判断边点重合
}
return true;//没有以上情况,可以放入该矩形
}
void dfs(int now){
if(now>n&&tot<maxn){
maxn=tot;//用maxn表示最小值,我是不是有点毛病……凑合看吧
return ;
}
if(now>n||tot>=maxn)return ;//函数递归的三种情况:已超出n,还没到n矩形面积和就比当前最小面积和大了,或者是已经放不进任何一个矩形了
for(int i=1;i<=k;i++){
int a=sqr[i].x1 ,b=sqr[i].y1 ,c=sqr[i].x3 ,d=sqr[i].y3 ;
if(check(now,i)){
int sum=(sqr[i].x3 -sqr[i].x1 )*(sqr[i].y3 -sqr[i].y1 )-(c-a)*(d-b);
tot+=sum;
dfs(now+1);
tot-=sum;
}
sqr[i].x1 =a,sqr[i].y1 =b,sqr[i].x3 =c,sqr[i].y3 =d;//记得开临时数存先前状态
}
return ;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d%d",&node[i].x ,&node[i].y );
}
dfs(1);
printf("%d\n",maxn);
return 0;
}
题后总结
又一次没有认真看题。。。题目说的“边线与顶点也都不能重合”被你吃了吗!?
zyb说的果然对,这种小数据范围的题就考虑爆搜,注意特判和剪枝.
u p d a t e update update
好像原先做法不是正解?正解发一波.