hdu4741

  2013年两场网络赛已经过了,之前的现场赛拿了多次铜牌,而这两场网络赛我们都表现得这么水,不由得感慨起来,ACM竞赛生涯就要画上句号了,甚至整个学习生涯中这种纯学术的竞赛都要完了。这两场网络表现得不好,痛定思痛,当然主要原因是我自己的水平太弱了,技不如人当然惨败了。赛后看各种报告和代码比较后也发现了,也许弱校弱的地方并不都是我们不够聪明和努力吧。所以这里我要特别吐槽一些地方。

  第一,我觉得学校本身投入度不够,和如今一些学校的教育目标和方式不是特别好。我有一万次想写信给校长,但是又怕文采不好起不了反应或者文章感情过于激昂惹来祸端,要是给记个过,就亏大了。为什么我觉得学校本应该是无私教学育人的,而学校很多时候做得像投资一样?比如,我真心选修一些高质量理学公共课程,诸如离散数学之类而学校没有,连高等数学、线性代数、概率论这样老师大都是直接教怎么解题、记公式背公式。连物理这样美妙的学科最后竟然成了跟毛概一样的东西,shit!我就不懂了,为什么大学物理和物理实验、概率论应该还是属于“阉割”版的。有时候,很认真做物理实验或者其他计算机实验的,也不知道老师们仔细看了报告了没有。最让人抓狂的是,也许在所有人都没有意识的时候,也许改你作业的是个水平菜得像个鸟一样的研究生,然后你改进了老师给的标准算法,他一个看不懂,这次作业就算交过了、刚刚及格!好了,说点重点吧,学校的理学诸如数学、物理这样的学科太弱,其他地方再好能好到哪里去,好景又能有多长。完全只懂工科毕业的同学,工作能力能胜过普通社会青年和农民大叔多少,甚至很多地方还要欠缺很多吧。而一些领导者却认为,短期看不到成效的教学投资不值得!

  第二,首先我还是想特别感谢一下我的教练,我觉得他的才华、智慧是毋庸置疑的,而且我觉得他在教学育人上是个特别有思想值得敬爱的老师。刚大一、甚至到大二的时候,我都还在之前的象牙塔里。到了大三,开始要全部投入进来。很幸运,第一次参加现场赛拿到了奖牌,可能是太紧张了,不然那时候真的可以拿到一个银牌。但是后面的路确实苦涩。有时候,很多算法并不像一般的算法那样来源于实际,容易吸收。特别是跟数学(离散数学)有关的,如果是第一次见到的,那就完全只能看了。而解决的办法只有一个——刷题!然后看各种不知道是不是原创的报告,各种猜各种若无边际的验证,(almost all on your own).

  好吧,还是回到主题吧。这道题的大意是给空间上两条直线,(每条直线给出两个点的坐标,轴坐标范围+-10^4)求公垂线段的长度及其两端点坐标

  虽然这道题弹了30+次,我还是很想说说我的思路。

  假设F是AB上的垂足,E是CD上的垂足。将AB向两端扩展,保证F会在AB中间,CD也是类似。

  然后三分在线段AB上取点X,在F附近的X能让|XD|+|CX|。对CD也是同样。

  这样算得Xab,Xcd。由于AB、CD被扩展了,所以这次的Xab、Xcd只能是粗略估计。

  假设粗略估计的精度是0.1,那么以Xab为起点往AB两个方向扩展1个单位长度得到新的AB,对Xcd也是同样。

  再次进行三分搜索答案。

  结果就一直在TLE和WA之间徘徊。因为题目中AB、CD可能重点,是零向量,无法扩展!我真想说脏话,为毛官方的说话搞一个专门的话题板,话题板那么多还不支持搜索,每翻一个页面等要等10秒!!!同样的问题,有的回复了有的没回复,这不是坑爹吗?整个过程个,admin一直在说No response,然后强调注意实际问题。怎么说呢?我承认这是一个能力,但是:第一发散思维往往是多方向的;另外我们有太多时候被教育要严格遵守描述, 这个时候要我们自主发挥,会很大程度加大运气因素而不是算法知识和编程水平较量了!

  好了,看了清华ACE的代码,理了一下思路。可读性还是挺好,重写了一下。求公共垂线段长还是很容易的,但是有个地方还是不理解。求路过的大神指教一下。

  贴个代码:

  

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<vector>
 6 #include<algorithm>
 7 using namespace std;
 8 struct point{
 9     double x,y,z;
10     point(double p1=0,double p2=0,double p3=0){ x=p1,y=p2,z=p3; }
11     void getAX(){ scanf("%lf%lf%lf",&x,&y,&z); }
12     void putAX(){ printf("%.6f %.6f %.6f",x,y,z); }
13     double getdist(point B=point()){ return sqrt((x-B.x)*(x-B.x)+(y-B.y)*(y-B.y)+(z-B.z)*(z-B.z)); }
14     point operator-(point B){ return point(x-B.x,y-B.y,z-B.z); }
15     point operator+(point B){ return point(x+B.x,y+B.y,z+B.z); }
16     point operator*(double rat){ return point(x*rat,y*rat,z*rat); }
17     point cross(point B){ return point(y*B.z-z*B.y,z*B.x-x*B.z,x*B.y-y*B.x); }
18     double dot(point B) { return x*B.x+y*B.y+z*B.z; }
19     void normalize(){ (*this)=(*this)*(1/this->getdist()); }
20     point normal(){ return (*this)*(1/this->getdist()); }
21 };
22 point A,B,C,D,k1,k2;
23 int main()
24 {
25     int cases; cin>>cases;
26     for(int cas=1;cas<=cases;cas++){
27         A.getAX(); B.getAX();
28         C.getAX(); D.getAX();
29         point AB=B-A,CD=D-C;
30         point ver=AB.cross(CD);
31         ver.normalize();
32         double len=(C-A).dot(ver);
33         printf("%.6f\n",fabs(len));
34         ver = ver*len;
35         //*********神算法,不理解***************
36         k1=AB.normal(), k2=CD.normal();
37         point AC=C-A;
38         point k1_k2=k1+k2;
39         double t1=AC.dot(k1_k2)/(k1_k2.getdist()*k1_k2.getdist());
40         k1_k2=k1-k2;
41         double t2=AC.dot(k1_k2)/(k1_k2.getdist()*k1_k2.getdist());
42         point F=A+k1*(t1+t2);
43         point E=C-k2*(t1-t2);
44         //**************************************
45         F.putAX(); printf(" ");
46         E.putAX(); printf("\n");
47     }
48     return 0;
49 }
View Code

 

posted on 2013-09-16 14:00  男神发量  阅读(323)  评论(0编辑  收藏  举报