点开了一个挑战题,不知道规则,第一个就当学习经验了。
两个小时,憋不住去趟厕所回来,时间不够了。另外,在自己机器和在线编译不一样。提交了也编译不正确。比如我声明了
struct ptr{};
然后用
struct ptr dot[n];
来声明数组,结果在线编译不成功:
23: error:: error: C2143: syntax error: : missing ';' before 'type'
然后搜到一篇说这个错误是VC编译器造成的(那就是说我用GCC编译成功不算,必须提交网上,按VC算?),说是变量声明在函数调用之后就会出错(函数调用不用使用本变量,任何一个函数调用皆可)。
如果真把结构体数组的声明放前边,更不可能成功,因为我要靠一个scanf来获得n的值啊~~~
20: error:: error: C2057: expected constant expression
20: error:: error: C2466: cannot allocate an array of constant size 0
20: error:: error: C2133: 'dot' : unknown size
除非,既然说了上限是1001,我就建立一个1001大小的固定数组?虽然很弱智很浪费空间,但是能避免这个错误。如下:
unsigned int n = 1001;
struct ptr dot[n];
这样,想获取新的n,比如3,可以直接覆盖,如果死活不让我scanf来更新n,好歹可以凑合进行下去。不过问题是有三个循环,那样要跑1000×1000×1000的数量级,很没有必要,而且,多余的那么多结构体,是不是要弄个初始值,到时候又怎么计算他们?不应该计算他们的。多余的点根本不应该存在~!
经实测,这样也不行:
20: error:: error: C2057: expected constant expression
20: error:: error: C2466: cannot allocate an array of constant size 0
20: error:: error: C2133: 'dot' : unknown size
不能使用
struct ptr dot[n];
即使前边定义了n为1001~!(感觉这个编译器挺坑啊~!)
主要思路:
其实就是遍历了:
三层循环,第一层是定点A,A依次尝试所有点。
第二层和第三层没什么差别,就是B和C。
只不过,要记得ABC三点出现重复时用个continue(自增运算可不行,会越界)跳过去。
难点就是循环最内层那个核心的角度处理功能:
很久不接触各种三角运算符,加上math里的函数也不经常用,尴尬了。
角度的计算公式都是现查的,现学现用,去网上倒是查到了atan2()函数,但是~遇到一个问题——角度不是死的,还需要想办法。
解决角度的思路:
使用相对坐标,确定了A坐标以后,把A坐标看成(0,0),B和C的坐标以A为零点,确定新的相对坐标;
atan2()函数是针对纵坐标差和横坐标差的,输出的结果是这对坐标差构成的——直线——相对x坐标轴的角度差~!也就是说,这是针对一条直线来的,不是针对两条线的夹角,我的解决办法就是分别给两条直线计算出和X轴的相对夹角,然后计算角度差。
还包括四个象限的处理问题。
依然有很多问题没有解决:
当时不停更改,变量设的也多而杂、有冗余,还有些“对付”上的代码,先把本地代码传上来存下:
1 #include<stdio.h>
2 #include<math.h>
3 //思路,遍历,三层循环,第一重循环找所有的点,第二重和第三重组成其他两点的所有组合>。
4 //不打算用数据结构了,自己记住有几个点
5 //但是点太多怎么动态储存呢?malloc
6 #define PI 3.1415926
7 struct ptr{
8 double x;
9 double y;
10 }
11
12 main(){
13 //get n
14 //加非法判断?3到1001~!
15 unsigned int n;
16 int i,j,k;
17 double tempAngle = 0;
18 double maxAngle = 0;
19 //记录结果的三个结构体变量
20 struct ptr A,B,C;
21 printf("input n:i\n");
22 scanf("%d",&n);
23 //临时变量
24 struct ptr tempj;
25 struct ptr tempk;
26 double angleKtoZero;
27 double angleJtoZero;
28 double tempx;
29 double tempy;
30
31 struct ptr dot[n];
32 for(i = 0;i < n;i++){
33 scanf("%lf %lf",&(dot[i].x),&(dot[i].y));
34 }
35 //遍历所有组合
36 for(i = 0;i < n;i++){
37 for(j = 0;j < n;j++){//需要消除重复,跳过去直接
38 if(j == i)
39 continue;
40 for(k = 0;k < n;k++){
41 if(k == j || k == i)
42 continue;
43 // 计算角度,存在哪?用一对变量,只要比他大,替换?
44 //atan应该排除负数情况,用绝对值对比~!不然容易出现差错,
45 //要不然就以A为0 0,把B C 转换成相对坐标。
46 tempj.x = dot[j].x - dot[i].x;
47 tempj.y = dot[j].y - dot[i].y;
48 tempk.x = dot[k].x - dot[i].x;
49 tempk.y = dot[k].y - dot[i].y;
50 tempx = tempj.x - tempk.x;
51 tempy = tempj.y - tempk.y;
52 /* if(tempx < 0)
53 tempx = -tempx;//not -=
54 if(tempy < 0)
55 tempy = -tempy;
56 */
57 angleKtoZero = atan2(tempj.x,tempj.y) * 180 / PI;
58 angleJtoZero = atan2(tempk.x,tempk.y) * 180 / PI;
59 //test
60 printf("%lf\n",angleJtoZero);
61 printf("%lf\n",angleKtoZero);
62
63 tempAngle = angleKtoZero - angleJtoZero;
64 if(tempAngle < 0){
65 tempAngle = -tempAngle;
66 }
67 if(tempAngle > 181){//因为不是严格180,先这么写
68 tempAngle -= 180;
69 }
70 double add;
71 add = tempAngle * 100000 % 10;
72 if(add >= 5)
73 tempAngle = tempAngle * 100000/10 + add;
74 else
75 tempAngle = tempAngle * 100000/10;
76
77 //现在主要不知道怎么解决角度大于90度的情况,因此时角度越大, tan反而越小
78 //直接用y的差距比上x的差距,是不是也太片面了,不是固定A为0点
79 //那就想办法创造以A为准的坐标系?
80 if(tempAngle > maxAngle){
81 maxAngle = tempAngle;
82 A.x = dot[i].x;
83 A.y = dot[i].y;
84 B.x = dot[j].x;
85 B.y = dot[j].y;
86 C.x = dot[k].x;
87 C.y = dot[k].y;
88 }
89 }
90 }
91 }
92
93 printf("The maxAngle is %lf\n",maxAngle);
94 printf("A:%lf %lf\n",A.x,A.y);
95 printf("B:%lf %lf\n",B.x,B.y);
96 printf("C:%lf %lf\n",C.x,C.y);
97
98
99 }
根据“反闭门造车”理论,这是我做的第一个题,即使解不出来也不能全当是个练习,最好是找找答案,学习一下现成的,成熟的解决方法,希望能找到参考答案。
另外,这是3星难度,还有2星难度,应该先看看2星难度的,循序渐进。
另一童鞋的思路和解答,也有缺陷,比如90度(90度的tan可是无穷,我用atan()都不知道怎么搞了)
http://blog.csdn.net/type_q/article/details/24512223