题目链接:

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(几何+二分)的更多相关文章

  1. Project Euler 44 Sub-string divisibility( 二分 )

    题意:五边形数由公式Pn=n(3n−1)/2生成,在所有和差均为五边形数的五边形数对Pj和Pk中,找出使D = |Pk − Pj|最小的一对:此时D的值是多少? 思路:二分找和差 /********* ...

  2. [project euler] program 4

    上一次接触 project euler 还是2011年的事情,做了前三道题,后来被第四题卡住了,前面几题的代码也没有保留下来. 今天试着暴力破解了一下,代码如下: (我大概是第 172,719 个解出 ...

  3. Python练习题 029:Project Euler 001:3和5的倍数

    开始做 Project Euler 的练习题.网站上总共有565题,真是个大题库啊! # Project Euler, Problem 1: Multiples of 3 and 5 # If we ...

  4. Project Euler 9

    题意:三个正整数a + b + c = 1000,a*a + b*b = c*c.求a*b*c. 解法:可以暴力枚举,但是也有数学方法. 首先,a,b,c中肯定有至少一个为偶数,否则和不可能为以上两个 ...

  5. 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 ...

  6. project euler 169

    project euler 169 题目链接:https://projecteuler.net/problem=169 参考题解:http://tieba.baidu.com/p/2738022069 ...

  7. 【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 × ...

  8. Project Euler 第一题效率分析

    Project Euler: 欧拉计划是一系列挑战数学或者计算机编程问题,解决这些问题需要的不仅仅是数学功底. 启动这一项目的目的在于,为乐于探索的人提供一个钻研其他领域并且学习新知识的平台,将这一平 ...

  9. Python练习题 049:Project Euler 022:姓名分值

    本题来自 Project Euler 第22题:https://projecteuler.net/problem=22 ''' Project Euler: Problem 22: Names sco ...

随机推荐

  1. <c:if test=""></c:if> 使用

    1.页面引用<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 2.整形判 ...

  2. Mysql学习总结(8)——MySql基本查询、连接查询、子查询、正则表达查询讲解

    查询数据指从数据库中获取所需要的数据.查询数据是数据库操作中最常用,也是最重要的操作.用户可以根据自己对数据的需求,使用不同的查询方式.通过不同的查询方式,可以获得不同的数据.MySQL中是使用SEL ...

  3. Struts(18)标签

    控件标签 Struts 2 的标签有一组标签.更easy控制流程页面运行.下面是重要的Struts2控制标签列表: if /else 标签: 这些标签运行可在每一种语言找到的一种基本条件流程. 'If ...

  4. leetCode 82.Remove Duplicates from Sorted List II (删除排序链表的反复II) 解题思路和方法

    Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numb ...

  5. Mvc异步

    <h3>MVC 自带的yibu请求</h3> <%-- 1.要执行的方法,2.控制器,3.Ajax操作--%> <%using (Ajax.BeginForm ...

  6. AIX lsof 命令

    1.查看某端口运行情况 如查看22端口运行情况 # lsof –i:22 # lsof –i:22 –r   ----每隔15秒显示22端口的监听情况.   2.查看活动的连接 如:查看ip地址为19 ...

  7. js简易留言板

      <!DOCTYPE html>   <html lang="en">   <head>   <meta charset="U ...

  8. NO.1 You must restart adb and Eclipse多种情形分析与解决方式

    一:错误提示 The connection to adb is down, and a severe error has occured. You must restart adb and Eclip ...

  9. Extjs, 使用GridPanel出现 Layout run failed

    当GridPanel被加入到容器,且容器的layout为vbox时候, 会出现 Layout run failed 后者GridPanel的尺寸没有撑满父容器 网上找到的解决的方法是.要给父容器设置一 ...

  10. Android经常使用自己定义控件(二)

           经常使用的Android自己定义控件分享 http://www.see-source.com//androidwidget/list.html?type=&p=1