hdu5251 凸包 旋转卡壳
来源:互联网 发布:幼儿网络学英语 编辑:程序博客网 时间:2024/05/13 14:34
传送门:hdu5251 矩形面积
接触了旋转卡壳不久,感觉很神奇……
这个题是要寻找一个矩形来覆盖住桌面上的小矩形,小矩形即四个点啦,所以就是
找一个矩形覆盖住这些点,也就要求一个凸包,再用矩形把凸包盖住,那就很明显的
是旋转卡壳了,类似旋转卡壳求凸包的宽度,只是这是求矩形面积的最小值
完整代码:
#include<cstdio>#include<cmath>#include<algorithm>#include<iostream>using namespace std;const int MAXN=1000005;const double PI=acos(-1.0);typedef long long ll;struct point{ double x,y;};point list[MAXN];point stack[MAXN];int top;/**叉积**/double cross(point p0,point p1,point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);}/**点积**/double dot(point p0,point p1,point p2){ return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);}/**距离的平方**/double dis(point p1,point p2){ return (double)(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y);}/**极角排序**/bool cmp(point p1,point p2){ double tmp=cross(list[0],p1,p2); if(tmp>0) return true; else if(tmp==0&&dis(list[0],p1)<dis(list[0],p2)) return true; else return false;}/**凸包**/void graham(int n){ int i; if(n==1) {top=0;stack[0]=list[0];} if(n==2) { top=1; stack[0]=list[0]; stack[1]=list[1]; } if(n>2) { for(i=0;i<=1;i++) stack[i]=list[i]; top=1; for(i=2;i<n;i++) { while(top>0&&cross(stack[top-1],stack[top],list[i])<=0) top--; top++; stack[top]=list[i]; } }}/**旋转卡壳**/double rotating_calipers(point p[],int n){ int k1=1,k2=1,k3=1; double ans=0x7FFFFFFF; p[n]=p[0]; for(int i=0;i<n;i++) { /**利用叉积的几何意义,来找距离p[i]-p[i+1]这条边的最远的点**/ while(fabs(cross(p[i],p[i+1],p[k1]))<fabs(cross(p[i],p[i+1],p[k1+1]))) k1=(k1+1)%n; /**这里求的点积,用了点积的几何意义,即p[i]-p[i+1]这条边再乘p[i]-p[k2]在 p[i]-p[i+1]上的投影,投影的长度便是叉积再除p[i]-p[i+1]的长度,下面在求矩形面积 时用到了这一点**/ while(dot(p[i],p[i+1],p[k2])<dot(p[i],p[i+1],p[k2+1])||dot(p[i],p[i+1],p[k2])<0) k2=(k2+1)%n;///这里找的是最右边的点,根据几何意义,这里的点积应该是正的 while(dot(p[i],p[i+1],p[k3])>dot(p[i],p[i+1],p[k3+1])||dot(p[i],p[i+1],p[k3])>0) k3=(k3+1)%n;///这里找的是最左边的点,根据几何意义,这里的点击应该是负的 double tmp=fabs(cross(p[i],p[i+1],p[k1])); double tmp1=dot(p[i],p[i+1],p[k2]); double tmp2=dot(p[i],p[i+1],p[k3]); double d=dis(p[i],p[i+1]); /**这里求面积,实际是凸包的某一“宽度”(不是严格意义上 的宽度)乘了两个叉积的差就是这个矩形了面积了**/ double s=tmp/d*(tmp1-tmp2); ans=min(ans,s); } return ans;}int main(){ int t; scanf("%d",&t); int cnt=0; while(t--) { cnt++; int n; scanf("%d",&n); int k=0; scanf("%lf%lf",&list[0].x,&list[0].y); for(int i=1;i<4*n;i++) { scanf("%lf%lf",&list[i].x,&list[i].y); if(list[i].y<list[k].y||(list[i].y==list[k].y&&list[i].x<list[k].x)) k=i; } swap(list[k],list[0]); sort(list+1,list+4*n,cmp); graham(4*n); printf("Case #%d:\n%lld\n",cnt,(ll)(rotating_calipers(stack,top+1)+0.5)); } return 0;}
阅读全文
0 0
- hdu5251 凸包 旋转卡壳
- HDU5251矩形面积(凸包+旋转卡壳求最小矩形覆盖)
- 凸包与旋转卡壳
- 凸包,旋转卡壳模板
- bzoj1069 凸包+旋转卡壳
- 凸包 (旋转卡壳)
- hdu2202 凸包+旋转卡壳
- 凸包旋转卡壳 模板
- 旋转卡壳——合并凸包
- POJ2187 Beauty Contest 凸包+旋转卡壳
- 旋转卡壳--凸包的直径
- 旋转卡壳---凸包的宽度
- TYVJ1464(凸包+旋转卡壳)
- 凸包及旋转卡壳求凸包直径
- POJ 2187 凸包+旋转卡壳
- 最圆点对,(凸包+旋转卡壳)
- 旋转卡壳——合并凸包
- [hoj 1489]ATDS[凸包][旋转卡壳]
- Oracle中的INSTR,NVL和SUBSTR函数的用法代码实例
- php變量
- Android (向服务器提交数据)
- Java List 和 数组之间的相互转化
- test
- hdu5251 凸包 旋转卡壳
- Java中浅拷贝与深拷贝的区别
- 分布式锁的实现
- 黑窗口下mysql导出导入数据库
- hdu 3068 最长回文 Manacher算法模板题
- MySQL 3306端口开启
- Ultimate Array
- jms入门
- Gson内部静态类与Activity传递数据产生的尴尬(Activity之间传递静态类)