bzoj 1185 [HNOI2007]最小矩形覆盖——旋转卡壳
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1185
矩形一定贴着凸包的一条边。不过只是感觉这样。
枚举一条边,对面的点就是正常的旋转卡壳。两边的那个点可以用点积的最小/大来判断,因为是投影。
然后调了一万年。不过好像把精度设成 1e-13 而不是 1e-8 就能过了。
和许多代码对拍,有各种各样的不同。也不知道自己是不是真的对了。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define db double using namespace std; const int N=5e4+5;const db eps=1e-13,INF=1e18; int n,tot; db ans; struct Node{ db x,y; Node(db a=0,db b=0):x(a),y(b) {} bool operator< (const Node &b)const {return x<b.x||(x==b.x&&y<b.y);} Node operator- (const Node &b)const {return Node(x-b.x,y-b.y);} Node operator+ (const Node &b)const {return Node(x+b.x,y+b.y);} db operator* (const Node &b)const {return x*b.x+y*b.y;} Node operator* (const db &b)const {return Node(x*b,y*b);} Node operator/ (const db &b)const {return Node(x/b,y/b);} }t[N],a[N],prn[5]; db Mx(db a,db b){return a>b?a:b;} int dcmp(db x){if(x>eps)return 1;if(x<-eps)return -1;return 0;} db cross(Node u,Node v){return u.x*v.y-u.y*v.x;} void upd(int &x){x>n?x-=n:0;} db Sqr(db x){return x*x;} db dist(Node u,Node v){return sqrt(Sqr(u.x-v.x)+Sqr(u.y-v.y));} int main() { scanf("%d",&tot); for(int i=1;i<=tot;i++)scanf("%lf%lf",&t[i].x,&t[i].y); sort(t+1,t+tot+1); for(int i=1;i<=tot;i++) {while(n>1&&dcmp(cross(a[n]-t[i],a[n-1]-t[i]))>=0)n--;a[++n]=t[i];} for(int i=tot-1,lm=n;i;i--) {while(n>lm&&dcmp(cross(a[n]-t[i],a[n-1]-t[i]))>=0)n--;a[++n]=t[i];} a[n]=a[1]; n--; ans=INF; int p0=2,cr=2,p1=3;//out of for() for(int i=1;i<=n;i++) { Node d=a[i+1]-a[i]; while(dcmp(cross(d,a[cr+1]-a[i])-cross(d,a[cr]-a[i]))>0)cr++,upd(cr); while(dcmp((a[p0+1]-a[i])*d-(a[p0]-a[i])*d)>=0)p0++,upd(p0);//>=? if(i==1)p1=cr;// while(dcmp((a[p1+1]-a[i])*d-(a[p1]-a[i])*d)<=0)p1++,upd(p1); db len=dist(a[i+1],a[i]); db s1=(a[p0]-a[i])*d/len, s2=(a[p1]-a[i])*d/len; db hi=cross(d,a[cr]-a[i])/len, ara=(s1-s2)*hi;//not /(2*len) if(dcmp(ara-ans)>=0)continue; ans=ara; // if(ara>=ans)continue; ans=ara; Node x1=d/len*(s1-s2); Node x2=d/len*hi; swap(x2.x,x2.y); x2.x=-x2.x;//*i prn[1]=a[i]+d/len*s2; prn[2]=prn[1]+x1; prn[3]=prn[2]+x2; prn[4]=prn[1]+x2; } printf("%.5f\n",ans);int id=1; for(int i=2;i<=4;i++) { Node u=prn[i],v=prn[id]; if(dcmp(u.y-v.y)<0||(!dcmp(u.y-v.y)&&dcmp(u.x-v.x)<0))id=i; } for(int j=1;j<=4;j++,id++,id>4?id=1:0) { if(!dcmp(prn[id].x))prn[id].x=0; if(!dcmp(prn[id].y))prn[id].y=0;//avoid -0 printf("%.5f %.5f\n",prn[id].x,prn[id].y); } return 0; }