Project Euler 292
Project Euler 292
题目
Pythagorean Polygons
We shall define a pythagorean polygon to be a convex polygon with the following properties:
- there are at least three vertices,
- no three vertices are aligned,
- each vertex has integer coordinates,
- each edge has integer length.
For a given integer $n$, define $P(n)$ as the number of distinct pythagorean polygons for which the perimeter is $\le n$.
Pythagorean polygons should be considered distinct as long as none is a translation of another.
You are given that $P(4)=1, P(30)=3655$ and $P(60)=891045$.
Find $P(120)$.
解决方案
这题可以使用动态规划来解决。令$N=120$。
我们可以将所有凸多边形的每一条边都加上同一个方向的箭头,以此方便进行我们进行动态规划状态的设计。
首先枚举出所有模长$\le N$的位移向量$(x,y,d),d=\sqrt{x^2+y^2}$,存储在数组$v$中,并且将$v$中所有向量按照极角进行排序。此处假设所有位移向量$v$已经从小到大排好序(也就是逆时针方向)。并且,我们已经离散化好所有极角,假设一共有$m$种不同的极角,且第$i$小的极角大小为$i$。我们还需要注意的是,同一极角下的向量最多只能用一个,否则将会造成两条共线的边退化成同一条边,这些向量已经存储在了$u[i]$中。
令状态$f(i,x,y,d)(i\ge 0,0\le d\le N)$表示从原点$(0,0)$起,使用了前$i$种极角不同的向量后,走到了位置$(x,y)$,并且走过距离为$d$的方案数。一开始没有进行任何位移时,就没有使用任何的位移向量,因此$f(0,0,0,0)=1$。
本题的动态规划过程考虑使用 “我为人人” 的方法,本质上是从当前状态使用了其中一个属于$u[i]$的向量走到了下一步,有如下两种转移方式。
$f(i,x,y,d)\rightarrow f(i+1,x,y,d)$,也就是说,第$i$种位移向量不被使用。
$f(i,x,y,d)\rightarrow f(i+1,x+p.x,y+p.y,d+p.d)$,其中位移向量$p\in u[i+1]$。
那么最终答案为$\displaystyle{\sum_{d=1}^N f(m,0,0,d)}-c(v)$。其中$c(v)$表示$v$中所有位移向量中,长度不超过$\dfrac{N}{2}$的个数的一半(因为我们还需要排除这种步行$2$步,直接掉头回到原点的情况。)
为了加快程序的运行效率,实现时进行了如下优化:
- 只考虑满足$x^2+y^2\le \dfrac{N^2}{4}$中的所有点,因为走出了这个范围的点最终没有足够距离走回点$(0,0)$。
代码
1 |
|