大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

洛谷P1034 【矩形覆盖】

Dfs+剪枝 保证正确性

复杂度:\(O(玄学)\)

此题标签是计算几何,可以极角排序然后DP,然而我因为想练搜索写了这份代码

对于每一个点,我们枚举它在哪一个矩形中。即对于每一个点,可以创建一个新矩阵储存它,也可以用旧的矩阵储存它。我们可以用vector来储存每个矩形中的点,当矩形中的点确定,矩形的大小和位置就是唯一确定的。

当n个点被放入k个矩形中时,我们计算出矩形的面积总和并更新答案。因为矩形不能重合,而矩形重合当且仅当一个矩形的一个顶点至少一个在另一个矩形中,两两枚举判断即可

光这样是无法AC此题的,我们还需要剪枝。显然随着点数的增加,矩形面积单调递增。所以我们每次计算出矩形的面积判断是否比答案优,即可AC此题

还有一个小剪枝,如果当前使用矩阵+未使用的点数<k,可以直接return

枚举K的做法只能通过K<=3的数据,不够严谨,而DP需要计算几何知识,对蒟蒻不友好,还是深搜最有保证

#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))

const int N=55,inf=0x3f3f3f3f;

int n,K,x1[5],y1[5],x2[5],y2[5],x[N],y[N],last=inf;
vector<int>sq[5];

inline void read(int &x){
	x=0;char f=1,c=getchar();
	while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); }
	while(isdigit(c)){ x=x*10+c-'0'; c=getchar(); }
	x*=f;
}

inline bool pd(int i,int j){
	if(x1[i]>=x1[j]&&x1[i]<=x2[j]&&y1[i]>=y1[j]&&y1[i]<=y2[j]) return 0;
	if(x2[i]>=x1[j]&&x2[i]<=x2[j]&&y1[i]>=y1[j]&&y1[i]<=y2[j]) return 0;
	if(x2[i]>=x1[j]&&x2[i]<=x2[j]&&y2[i]>=y1[j]&&y2[i]<=y2[j]) return 0;
	if(x1[i]>=x1[j]&&x1[i]<=x2[j]&&y2[i]>=y1[j]&&y2[i]<=y2[j]) return 0;
	return 1;
}

inline int sum(int num){
	mem(x1,0x3f),mem(y1,0x3f);
	mem(x2,0),mem(y2,0);
	go(i,1,num-1)
		for(int j=0;j<sq[i].size();++j){
			x1[i]=min(x1[i],x[sq[i][j]]);
			y1[i]=min(y1[i],y[sq[i][j]]);
			x2[i]=max(x2[i],x[sq[i][j]]);
			y2[i]=max(y2[i],y[sq[i][j]]);
		}
	go(i,1,num-1)
		go(j,i+1,num-1){
			if(!pd(i,j)) return inf;
		}
	static int ans;
	ans=0;
	go(i,1,num-1) ans+=(x2[i]-x1[i])*(y2[i]-y1[i]);
	return ans;
}

void dfs(int p,int num){
	static int ans;
	if((ans=sum(num))>=last) return;
	if(n-p+num<K) return;
	if(p==n+1&&num==K+1){ if(ans<last) last=ans; } return; }
	if(num<=K){
		sq[num].push_back(p);
		dfs(p+1,num+1);
		sq[num].pop_back();
	}
	if(num>1){
		go(i,1,num-1){
			sq[i].push_back(p);
			dfs(p+1,num);
			sq[i].pop_back();
		}
	}
}

int main(){
	//freopen("input.txt","r",stdin);
	read(n),read(K);
	go(i,1,n) read(x[i]),read(y[i]);
	dfs(1,1);
	printf("%d",last);
	return 0;
}
posted @ 2019-09-24 17:18  White_star  阅读(230)  评论(0编辑  收藏  举报
}