编程挑战——最大角度

6 篇文章 0 订阅

点开了一个挑战题,不知道规则,第一个就当学习经验了。

两个小时,憋不住去趟厕所回来,时间不够了。另外,在自己机器和在线编译不一样。提交了也编译不正确。比如我声明了

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









  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值