bzoj1038
来源:互联网 发布:sublime js高亮插件 编辑:程序博客网 时间:2024/05/20 20:55
一道很棒的题,思维难度不大,但是很考实现细节。
做了此题发现计算几何有点入门了。
#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>using namespace std;const double eps = 1e-8;double cc(double a){if (fabs(a) < eps)return 0;elsereturn a;}struct pointt{double x, y;pointt(double x, double y) :x(x), y(y){}pointt(){}};struct linee{double a, b;pointt start, end;linee(pointt aa, pointt bb){a = cc(aa.y - bb.y) / (aa.x - bb.x);b = cc(bb.y - a*bb.x);start = aa, end = bb;}linee(){}};bool comm(linee a, linee b){if (fabs(a.a - b.a) < eps)return a.b > b.b;return a.a < b.a;}struct com{pointt a;int l, r;com(){l = -1, r = -1;}};com p[500],getp[500];linee l[5000],templ[5000];linee getl[5000];int n,tot,totp;int first, last;//二分的关键是 l r取值要交叉即若r=mid 那么l只能是mid+1,像l=mid,r=mid-1这中情况重合了就会导致死循环,若判断最大值用mid+1比较若是最小值用mid比较。//这里写什么bound的时候因为r>=x是恒成立的如果数列中没有等于x的数那么r是刚好大于x的但由于写得是lower_bound所以要特判一下;int lower_bound(com a,com *p,int l,int r){while (l < r){int mid = (l + r) >> 1;if (p[mid].a.x>=a.a.x){r= mid;}elsel = mid+1;}return p[r].a.x>a.a.x?r-1:r;}pointt operator+(pointt a, pointt b){return pointt(a.x + b.x, a.y + b.y);}pointt operator-(pointt a, pointt b){return pointt(a.x - b.x, a.y - b.y);}double operator*(pointt a, pointt b){return a.x*b.x + a.y*b.y;}double dot(pointt a, pointt b){return a.x*b.y - a.y*b.x;}bool isonleft(pointt a, linee b){double y = b.a*a.x + b.b;return a.y > y;}pointt inter(linee a, linee b){double x = (b.b - a.b) / (a.a - b.a);double y = a.a*x + a.b;pointt c = pointt(x, y);return c;}//getl里的a b代表 y=ax+b getp里的l r代表左右直线的编号 a代表左右直线的交点void halfmat(){first = last = 1;getl[first] = l[1];for (int i = 2; i < tot; i++){if (fabs(l[i].a - getl[last].a) < eps)continue;//处理平行情况while (last - first >= 1 && !isonleft(inter(getl[last], getl[last - 1]), l[i]))last--;while (last - first >= 1 && !isonleft(inter(getl[first], getl[first + 1]), l[i]))first++;last++;getl[last] = l[i];//此题特殊不用进行最后的缝合。}getp[totp].l = first; getp[totp].r = first;getp[totp++].a = pointt(p[1].a.x, getl[first].a*p[1].a.x + getl[first].b);//这是为了以后lower_bound找的时候不会出问题for (int i = first + 1; i <= last; i++){getp[totp].l = i - 1; getp[totp].r = i;getp[totp++].a = inter(getl[i], getl[i - 1]);}getp[totp].l = last; getp[totp].r = last;getp[totp++].a = pointt(p[n].a.x, getl[last].a*p[n].a.x + getl[last].b);}int main(){scanf("%d", &n);tot = 1; totp = 1;for (int i = 1; i <= n; i++){scanf("%lf", &p[i].a.x);}for (int i = 1; i <= n; i++){scanf("%lf", &p[i].a.y);}p[1].l = p[1].r = 1;for (int i = 2; i <=n; i++){l[tot++] = linee(p[i].a, p[i - 1].a);p[i].l = tot - 1, p[i - 1].r = tot - 1;}p[n].l = p[n].r = tot - 1;for (int i = 1; i <tot; i++)templ[i] = l[i];//这一定要存储一个临时的因为排序后就变了sort(l+1, l + tot, comm);halfmat();if (last == 1)printf("0.000\n");else{double ans = 1000000000000000000;//说是绝对值小于100,评测的时候尼玛有的数据就大了2333for (int i = 1; i < totp; i++){if (i == 1 || i == totp - 1)continue;//你并不能考虑虚拟节点!!!因为如果第一和第二条线的交点在范围里面或是外面情况是不一样的。int st = lower_bound(getp[i], p,1,n);double y = -1000000000;if(getp[i].a.x<=p[n].a.x&&getp[i].a.x>=p[0].a.x) //这一定要排除隐患y = templ[p[st].r].a*getp[i].a.x + templ[p[st].r].b;ans = min(ans, cc(getp[i].a.y - y));}for (int i = 1; i <=n; i++){int st = lower_bound(p[i], getp,1,totp-1);double y = -1000000000;y = getl[getp[st].r].a*p[i].a.x + getl[getp[st].r].b;ans = min(ans, cc(y - p[i].a.y));//这一定要进行误差分析!!!!}printf("%.3lf\n", ans);}return 0;}
阅读全文
0 0
- bzoj1038
- bzoj1038: [ZJOI2008]瞭望塔
- 【ZJOI2008】【BZOJ1038】瞭望塔
- bzoj1038[ZJOI2008]瞭望塔
- BZOJ1038 瞭望塔
- bzoj1038【ZJOI2008】瞭望塔
- bzoj1038: [ZJOI2008]瞭望塔
- bzoj1038 [ZJOI2008]瞭望塔
- bzoj1038: [ZJOI2008]瞭望塔
- bzoj1038 [ZJOI2008]瞭望塔
- bzoj1038 [ ZJOI2008 ] -- 模拟退火+二分
- [BZOJ1038]ZJOI2008瞭望塔|半平面交
- bzoj1038 瞭望塔 半平面交
- 【bzoj1038】【ZJOI2008】【瞭望塔】【半平面交】
- [半平面交] BZOJ1038: [ZJOI2008]瞭望塔
- bzoj1038 瞭望塔【半平面交】
- 【半平面交】【计算几何】[BZOJ1038][ZJOI2008]瞭望塔
- 【半平面交】[ZJOI2008][HYSBZ\BZOJ1038]瞭望塔
- Linux文件权限和控制
- JavaWeb中的Servlet
- 前后台时间相差一天的问题
- CentOS7.x 常用命令
- bzoj4709 -- 决策单调性优化DP
- bzoj1038
- 深入浅出妙用 Javascript 中 apply、call、bind
- JSP的9大内置对象(隐式对象)
- mysql 重装
- 【python】python中的print函数以及产生随机数据的方式
- Java基础篇-简介
- concurrent包
- @SuppressWarnings注解用法详解
- python--leetcode 537. Complex Number Multiplication