题解 P1034 【矩形覆盖】
这么好(shui)的题目怎么能不上随机化搜索呢
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//思路:随机化搜索+贪心(从今年D1可以看出贪心是多么重要的能力(然而D1AK也救不了我D2爆炸QAQ(事实证明D2还是多打暴力为上策))) //每次以一定的概率进行贪心选择或随机选择 //贪心策略为将这个点加入一个矩形,选择代价最小的一个(很明显是错的,所以要随机化搜索辅助) #include<bits/stdc++.h> using namespace std; int ans=2000000000; int n,k; struct lj { int x,y; }point[59]; int x[5],xx[5],y[5],yy[5];//万能头不能用y1,所以就叫y,yy吧ovo int main() { srand(time(0)); scanf("%d %d",&n,&k); for(int i=1;i<=n;++i) { scanf("%d %d",&point[i].x,&point[i].y); } for(int iii=1;iii<=250000;++iii) { srand(rand());//其实没用哦0.0 random_shuffle(point+1,point+n+1);//随机序列,左闭右开 for(int j=1;j<=k;j++)//初始化,每个矩阵里至少要有一个点,也是为什么要随机化序列的原因之一 { x[j]=xx[j]=point[j].x; y[j]=yy[j]=point[j].y; } for(int j=k+1;j<=n;j++) { int mn=2000000000,cs; if(rand()%100+1<=70)//以70%的概率选择贪心,似乎70—90的概率都能过 { for(int ii=1;ii<=k;ii++) { if((max(xx[ii],point[j].x)-min(x[ii],point[j].x))*(max(yy[ii],point[j].y)-min(y[ii],point[j].y))-(xx[ii]-x[ii])*(yy[ii]-y[ii])<mn) { mn=(max(xx[ii],point[j].x)-min(x[ii],point[j].x))*(max(yy[ii],point[j].y)-min(y[ii],point[j].y))-(xx[ii]-x[ii])*(yy[ii]-y[ii]); cs=ii; } } } else cs=rand()%k+1;//不然随机 //改变被选择的矩形的大小 xx[cs]=max(xx[cs],point[j].x); x[cs]=min(x[cs],point[j].x); yy[cs]=max(yy[cs],point[j].y); y[cs]=min(y[cs],point[j].y); } int tot=0; for(int i=1;i<=k;i++) { tot+=(xx[i]-x[i])*(yy[i]-y[i]);//统计答案 } for(int i=1;i<k;i++) { for(int j=i+1;j<=k;j++) { if((x[i]==x[j]||x[i]==xx[j]||xx[i]==x[j]||xx[i]==xx[j])&&(y[i]==y[j]||y[i]==yy[j]||yy[i]==y[j]||yy[i]==yy[j])) tot=200000000;//判断顶点重合 if((x[i]==x[j]||x[i]==xx[j]||xx[i]==x[j]||xx[i]==xx[j])&&((y[i]<yy[j]&&yy[i]>y[j])||(y[j]<yy[i]&&yy[j]>y[i]))) tot=200000000;//纵边重合 if((y[i]==y[j]||y[i]==yy[j]||yy[i]==y[j]||yy[i]==yy[j])&&((x[i]<xx[j]&&xx[i]>x[j])||(x[j]<xx[i]&&xx[j]>x[i]))) tot=200000000;//横边重合 } } ans=min(ans,tot); } cout<<ans; return 0; }
突然发现自己唯二的题解都是些奇奇怪怪的算法呢...
请大家尽情hack吧ovo