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 ...
随机推荐
- 【Uva 12105】Bigger is Better
[Link]: [Description] 让你用最多n根棍子,组成一个数字,使得它能够被m整除; 数字1..9分别需要用-根棍子. 要求这个数字尽可能地大; 然后输出这个数字. [Solution] ...
- Bmob移动后端云服务平台--Android从零開始--(一)何为Bmob
Bmob移动后端云服务平台--Android从零開始--(一)何为Bmob 在正式的项目开发中,单client不能满足我们的需求,须要实现client与服务端的连接. 而在编写Android服务端代码 ...
- 动态规划 LCS,LIS
1.最大连续子序列 dp[i]=max(dp[i-1]+a[i],a[i]) 以i为结尾 2.最大不连续子序列 dp[i]=max(dp[j]+a[i],dp[j]) 3.最大连续递增子序列 if a ...
- vim 配置.vimrc文件
下面这个.vimrc文件是根据公司里的一个前辈配置的,这里记录下,方便以后使用.它的功能,其实跟网上很多.vimrc配置的相比,还是小儿科.我记录下来,主要还是因为自己已经习惯了这个工作环境跟快捷键. ...
- Android 实现QQ、微信、新浪微博和百度第三方登录
前言: 对于大多数的APP都有第三方登录这个功能,自己也做过几次,最近又有一个新项目用到了第三方登录,所以特意总结了一下关于第三方登录的实现,并拿出来与大家一同分享: 各大开放平台注册账户获取AppK ...
- 【基础篇】点击Button按钮更换图片
我们在开发的过程中,往往为了美化界面的需要,会修改按钮的默认外观,而因为Android中的按钮有三种状态—默认,被点击,被选中.所以,如果要改变按钮的外观,需要对这三种情况都做出修改,也许在以往,我们 ...
- GDSOI2019划水记
Day -9 北京集训结束,飞回广州浪两天后回校. Day -2 回家休整,打麻将技术进一步提高. Day 0 前往佛山入住酒店,论被人用大床房换双人房是什么体验??(一个人住真的舒服) 待在房间背模 ...
- gdal读写图像分块处理
转自赵文原文 gdal读写图像分块处理(精华版) Review: 用gdal,感觉还不如直接用C++底层函数对遥感数据进行处理.因为gdal进行太多封装,如果你仅仅只是Geotif等格式进行处理,IO ...
- Hibernate之关于多对多单向关联映射
[Hibernate]之关于多对多单向关联映射 老师和学生,最典型的多对多关联, Teacher和Student.所谓单向意思就是说.老师知道自己的教的是哪些学生而学生不知道是哪些老师教. 也能够这么 ...
- 測试CPU支持指令集AVX,AVX2,SSE情况的代码【VS2010调试通过】
完整代码例如以下所看到的 http://download.csdn.net/detail/vbskj/7723827 本人的測试结果 watermark/2/text/aHR0cDovL2Jsb2cu ...