Project Euler 363 Bézier Curves(几何+二分)
题目链接:
https://projecteuler.net/problem=363
题目:
A cubic Bézier curve is defined by four points: \(P_0, P_1, P_2\) and \(P_3\).

The curve is constructed as follows:
On the segments \(P_0P_1\), \(P_1P_2\) and \(P_2P_3\) the points \(Q_0,Q_1\) and \(Q_2\) are drawn such that
\(P_0Q_0 / P_0P_1 = P_1Q_1 / P_1P_2 = P_2Q_2 / P_2P_3 = t (t in [0,1]).\)
On the segments \(Q_0Q_1\) and \(Q_1Q_2\) the points \(R_0\) and \(R_1\) are drawn such that
\(Q_0R_0 / Q_0Q_1 = Q_1R_1 / Q_1Q_2 = t\) for the same value of \(t\).
On the segment \(R_0R_1\) the point B is drawn such that \(R_0B / R_0R1 = t\) for the same value of \(t\).
The Bézier curve defined by the points \(P_0, P_1, P_2, P_3\) is the locus of B as \(Q_0\) takes all possible positions on the segment \(P_0P_1\).
(Please note that for all points the value of t is the same.)
At this (external) web address you will find an applet that allows you to drag the points \(P_0, P_1, P_2 and P_3\) to see what the Bézier curve (green curve) defined by those points looks like. You can also drag the point \(Q_0\) along the segment \(P_0P_1\).
From the construction it is clear that the Bézier curve will be tangent to the segments \(P_0P_1\) in \(P_0\) and \(P_2P_3\) in \(P_3\).
A cubic Bézier curve with $P_0=(1,0), P_1=(1,v), P_2=(v,1) and P_3=(0,1) $is used to approximate a quarter circle.
The value v > 0 is chosen such that the area enclosed by the lines \(OP_0, OP_3\) and the curve is equal to π/4 (the area of the quarter circle).
By how many percent does the length of the curve differ from the length of the quarter circle?
That is, if L is the length of the curve, calculate 100 × (L − π/2)/(π/2)
Give your answer rounded to 10 digits behind the decimal point.
题解:
这道题超级有意思。
不查一下wiki根本不知道怎么下手...
https://en.wikipedia.org/wiki/Bézier_curve
因为Bézier curve上的4个点是:\((1, 0), (1, v), (v, 1), (0, 1)\)
所以从wiki上得Specific cases可以知道,将4个点代入 \(B(t)\) 得到 \(x(t)\)和 \(y(t)\):
+ - \(B(t) = (1-t)^3 P_0 + 3(1-t)^2 t P_1 + 3(1-t) t^2 P_2 + t^3 P_3\)
+ - \(x(t) = (1 - t)^3 + 3(1-t)^2t + 3(1-t) t^2 v\)
+ - \(y(t) = 3(1-t)^2tv + 3(1-t) t^2 + t^3\)
其中,\(v\) 未知,\(0 <= t <= 1\). \(x(t), y(t)\) 就是计算曲线上的坐标。
然后我们直接二分 \(v\) 就可以了。
得到 \(v\) 后可以直接计算曲线的长度(arc_length_of_a_curve),也可以将曲线化为无数的小线段进行逼近。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e8;
const int mod = 1e9;
const double pi = acos(-1.0);
double x(double t, double v)
{
return (1-t)*(1-t)*(1-t) + 3*(1-t)*(1-t)*t + 3*(1-t)*t*t*v;
}
double y(double t, double v)
{
return 3*t*(1-t)*(1-t)*v + t*t*t + 3*t*t*(1-t);
}
double cal_distance(double a,double b,double c,double d)
{
return (double)sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
//https://en.wikipedia.org/wiki/B%C3%A9zier_curve
int main(int argc, char const *argv[]) {
int dot = 500000;
double left = 0.0, right = 1.0;
double v = 0.0, area = 0.0;
while (right - left > 1e-15) {
v = (right + left) / 2;
area = 0.0;
for(int i = 0;i < dot;i++) {
double now = (double) i / dot * 1.0;
double next = (double) (i+1) / dot * 1.0;
//cross product
area += ( x(now,v) * y(next,v) - x(next,v) * y(now,v) ) / 2.0;
}
if(area > pi / 4.0) {
right = v;
}
else {
left = v;
}
}
std::cout << "binary search finish !" << '\n';
std::cout << "left = " << left << '\n';
std::cout << "v = " << v << '\n';
std::cout << "area = " << area << '\n';
double L = 0.0;
dot = 500000;
for(int i = 0;i < dot;i++){
double now = (double)i / dot * 1.0;
double next = (double)(i + 1) / dot * 1.0;
L += cal_distance(x(now, v), y(now, v), x(next, v), y(next, v));
}
printf("%.12f\n",100.0*(L-pi/2.0)/pi*2.0);
cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
return 0;
}
Project Euler 363 Bézier Curves(几何+二分)的更多相关文章
- Project Euler 44 Sub-string divisibility( 二分 )
题意:五边形数由公式Pn=n(3n−1)/2生成,在所有和差均为五边形数的五边形数对Pj和Pk中,找出使D = |Pk − Pj|最小的一对:此时D的值是多少? 思路:二分找和差 /********* ...
- [project euler] program 4
上一次接触 project euler 还是2011年的事情,做了前三道题,后来被第四题卡住了,前面几题的代码也没有保留下来. 今天试着暴力破解了一下,代码如下: (我大概是第 172,719 个解出 ...
- Python练习题 029:Project Euler 001:3和5的倍数
开始做 Project Euler 的练习题.网站上总共有565题,真是个大题库啊! # Project Euler, Problem 1: Multiples of 3 and 5 # If we ...
- Project Euler 9
题意:三个正整数a + b + c = 1000,a*a + b*b = c*c.求a*b*c. 解法:可以暴力枚举,但是也有数学方法. 首先,a,b,c中肯定有至少一个为偶数,否则和不可能为以上两个 ...
- Project Euler 44: Find the smallest pair of pentagonal numbers whose sum and difference is pentagonal.
In Problem 42 we dealt with triangular problems, in Problem 44 of Project Euler we deal with pentago ...
- project euler 169
project euler 169 题目链接:https://projecteuler.net/problem=169 参考题解:http://tieba.baidu.com/p/2738022069 ...
- 【Project Euler 8】Largest product in a series
题目要求是: The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × ...
- Project Euler 第一题效率分析
Project Euler: 欧拉计划是一系列挑战数学或者计算机编程问题,解决这些问题需要的不仅仅是数学功底. 启动这一项目的目的在于,为乐于探索的人提供一个钻研其他领域并且学习新知识的平台,将这一平 ...
- Python练习题 049:Project Euler 022:姓名分值
本题来自 Project Euler 第22题:https://projecteuler.net/problem=22 ''' Project Euler: Problem 22: Names sco ...
随机推荐
- Qt Quick 之 PathView 具体解释
PathView ,顾名思义,沿着特定的路径显示 Model 内的数据. Model 能够是 QML 内建的 ListModel . XmlListModel ,也能够是在 C++ 中实现的 QAbs ...
- Python 查找Twitter中特定话题中最流行的10个转发Tweet
CODE: #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2014-7-4 @author: guaguastd @name: fi ...
- 对string的一些扩展函数
对string作了一些扩展,包含string转化为int.string转化为double.string转化为bool.打印系统当前时间.但没有解决数据溢出的问题,请大神帮忙解决! //头文件 /*pa ...
- ThinkPHP5如何修改默认跳转成功和失败页面
ThinkPHP5如何修改默认跳转成功和失败页面 一.总结 一句话总结:直接修改默认跳转页面对应的模板文件的路径:'dispatch_success_tmpl' => APP_PATH . 'i ...
- Onvif开发之客户端鉴权获取参数篇
前面一篇已经介绍了客户端如何发些设备,下面这篇简单介绍下在发现设备后,如何通过ONVIF协议来获取设备的相关参数 ONVIF中不管是客户端还是设备端,最先实现的接口都是关于能力的那个接口,在客户端实现 ...
- C# 开发 —— 数组类对象接口
数组类型是从抽象基类 Array 派生的引用类型,通过new运算符创建数组并将数组元素初始化为他们的默认值 一维数组 type[] arrayname; 数组的长度不是声明的一部分,而且数组必须在访问 ...
- JavaScript--数据结构与算法之散列
散列:实现散列表的数据后可以快速地实现插入或者删除.但是对于实现查找操作则效率非常的低.散列表的底层是数组实现的,长度是预先设定,可以随时根据需求增加.所有的元素根据和该元素对应的键,保存在特定的位置 ...
- ssm 框架学习-1
理论理解 +项目阅读 SpringSpring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象.Spring的核心思想是IoC(控制反转),即 ...
- 【Hello 2018 C】Party Lemonade
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 处理出凑够2^j最少需要花费多少钱. 即试着把第i种物品买2^(j-i)个,看看会不会更便宜 记录在huafei[0..31]中 然 ...
- SQL优化工具SQLAdvisor使用(转)
一.简介 在数据库运维过程中,优化SQL是业务团队与DBA团队的日常任务.例行SQL优化,不仅可以提升程序性能,还能够降低线上故障的概率. 目前常用的SQL优化方式包括但不限于:业务层优化.SQL逻辑 ...