Project Euler 177

Project Euler 177

题目

Integer angled Quadrilaterals

Let ABCD be a convex quadrilateral, with diagonals AC and BD. At each vertex the diagonal makes an angle with each of the two sides, creating eight corner angles.

For example, at vertex \(A\), the two angles are \(CAD, CAB\).

We call such a quadrilateral for which all eight corner angles have integer values when measured in degrees an “integer angled quadrilateral”. An example of an integer angled quadrilateral is a square, where all eight corner angles are \(45°\). Another example is given by \(DAC = 20°, BAC = 60°, ABD = 50°, CBD = 30°, BCA = 40°, DCA = 30°, CDB = 80°, ADB = 50°\).

What is the total number of non-similar integer angled quadrilaterals?

Note: In your calculations you may assume that a calculated angle is integral if it is within a tolerance of \(10^{-9}\) of an integer value.

解决方案

本题在枚举的过程中需要注意旋转、翻转的情况,需要去重。需要通过一些手段尽量减少枚举量。

只需要枚举其中四个角\(DAC,BAC,ABD,CBD\)的大小,就可以通过正弦定理余弦定理确定另外\(4\)个角的值,然后判断这些角是否都为整数。

具体过程见代码。

加上旋转,翻转后有八种方案,我们只保留其中一种。

代码

本代码根据题目下Thread的一份代码进行优化修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <bits/stdc++.h>
using namespace std;

double pi = acos(-1.0);
double sina[184];
double cosa[184];
unsigned hs(int a, int b, int c, int d) {
return (a << 24) | (b << 16) | (c << 8) | d;
}

int main() {
int ans = 0;
for (int i = 0; i <= 180; i++) {
sina[i] = sin(i * pi / 180);
cosa[i] = cos(i * pi / 180);
}
// 不失一般性,枚举的角DAC是八个角中最小的。后续计算中如果发现有比这更小的角,则直接跳出循环。
for (int DAC = 1; DAC <= 45; DAC++)
// AB边上的另外两个角ABD,CBD至少有DAC这么大。
for (int BAC = DAC; BAC <= 180 - DAC * 3; BAC++)
// CBD至少有DAC这么大。
for (int ABD = DAC; ABD <= 180 - 2 * DAC - BAC; ABD++)
for (int CBD = DAC; CBD <= 180 - DAC - BAC - ABD; CBD++) {
int BCA = 180 - (BAC + ABD + CBD);
int ADB = 180 - (DAC + BAC + ABD);
// AB=1
double AC = sina[ABD + CBD] / sina[BCA];
double AD = sina[ABD] / sina[ADB];
double DC = sqrt(AC * AC + AD * AD - 2 * AC * AD * cosa[DAC]);
double tmpACD = acos((AC * AC + DC * DC - AD * AD) / (2 * AC * DC)) * 180 / pi;
int ACD = int(round(tmpACD));
if (fabs(tmpACD - ACD) > 1e-9) continue;
if (ACD < DAC) break;
int CDB = 180 - (DAC + ACD + ADB);
if (CDB < DAC) break;
unsigned h = hs(DAC, BAC, ABD, CBD);
if (h > hs(ABD, CBD, BCA, ACD)) continue;
if (h > hs(BCA, ACD, CDB, ADB)) continue;
if (h > hs(CDB, ADB, DAC, BAC)) continue;
if (h > hs(BAC, DAC, ADB, CDB)) continue;
if (h > hs(CBD, ABD, BAC, DAC)) continue;
if (h > hs(ACD, BCA, CBD, ABD)) continue;
if (h > hs(ADB, CDB, ACD, BCA)) continue;
++ans;
}
printf("%d\n", ans);
return 0;
}

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
Ujimatsu Chiya 微信 微信
Ujimatsu Chiya 支付宝 支付宝