Chinaunix首页 | 论坛 | 博客
  • 博客访问: 81068
  • 博文数量: 32
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 284
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-26 14:00
个人简介

有梦想的人,正在努力

文章分类

全部博文(32)

文章存档

2015年(32)

我的朋友

分类: C/C++

2015-04-26 14:09:03

        这道题的大概意思就是在一座金字塔的底部,有一个宝藏,但是底部这一层里面有很多纵横交错的墙,而宝藏就在其中一个由这些墙构成的房间里面。每面墙的两头都在金字塔最外面的四周的墙上。然后需要在每面墙的中间开一道门,问最少开几道门就能进到有宝藏的那个房间。

如图:

其实我们不用枚举四周墙的中点,枚举每一面墙的端点就行了。判断这个端点和宝藏构成的直线与里面的直线(墙)有多少个交点就行了。而且只需要判断非规范相交(端点在直线上的情况在这题中不会出现)。

AC代码如下:


  1. #include <iostream>
  2. #include <cmath>
  3. using namespace std;
  4. struct Point{
  5.     double x;
  6.     double y;
  7. }Goal; //

  8. struct Wall{
  9.     Point a;
  10.     Point b;
  11. }walls[40]; //

  12. double direction(Point p1, Point p2, Point p3) //caculate (p3-p1)X(p2-p1) //判断叉积
  13. {
  14.     return (p3.x-p1.x)*(p2.y-p1.y) - (p2.x-p1.x)*(p3.y-p1.y);
  15. }

  16. bool segments_intersect(Point p1, Point p2, Point p3, Point p4) //判断是否相交(此方法可参见《算法导论》-计算几何那一章)
  17. {
  18.     double d1 = direction(p1, p2, p4);
  19.     double d2 = direction(p1, p2, p3);
  20.     double d3 = direction(p3, p4, p1);
  21.     double d4 = direction(p3, p4, p2);
  22.     if(((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 < 0 && d4 > 0) || (d3 > 0 && d4 < 0)))
  23.         return true;
  24.     return false;
  25. }

  26. int main()
  27. {
  28.     int n;
  29.     int ct[40][2] = {{0}};
  30.     cin >> n;
  31.     if(0 == n) //注意N为零的情况下还是需要读入宝藏的位置的,我之前就因为这个WA了好多次
  32.     {
  33.         cin >> Goal.x >> Goal.y;
  34.         cout << "Number of doors = 1\n";
  35.     }
  36.     else
  37.     {
  38.         for(int i = 0; i < n; ++i)
  39.             cin >> walls[i].a.x >> walls[i].a.y >> walls[i].b.x >> walls[i].b.y; //读入墙
  40.         cin >> Goal.x >> Goal.y;
  41.         for(int i = 0; i < n; ++i)
  42.         {
  43.             for(int j = 0; j < n; ++j) //判断交点数
  44.             {
  45.                 if(segments_intersect(walls[j].a, walls[j].b, walls[i].a, Goal)) ++ct[i][0]; //一面墙的端点a
  46.                 if(segments_intersect(walls[j].a, walls[j].b, walls[i].b, Goal)) ++ct[i][1]; //该面墙的端点b
  47.             }
  48.         }
  49.     //找出最小的值
  50.         int minDoors = ct[0][0];
  51.         for(int i = 0; i < n; ++i)
  52.             for(int j = 0; j < 2; ++j)
  53.                 if(minDoors > ct[i][j]) minDoors = ct[i][j];
  54.         cout << "Number of doors = " << minDoors + 1 << endl;
  55.     }
  56.     return 0;
  57. }

------------------------------------------------------------------------------------------------------------------------


而在该题的Discuss中还看到一个人的源码,但是无法理解,没仔细研究,还是贴上来吧:


  1. #include<iostream>
  2. #include<cstdlib>
  3. using namespace std;
  4. int geti(int x,int y)
  5. {
  6.     if(y==0)return x-1;
  7.     if(x==100)return 99+y;
  8.     if(y==100)return 299-x;
  9.     return 399-y;
  10. }
  11. int main()
  12. {
  13.     int i=0,n,x0[30],y0[30],x1[30],y1[30],from,to,s[400]={};
  14.     double x,y,k;
  15.     for(cin>>n;i<n;i++)cin>>x0[i]>>y0[i]>>x1[i]>>y1[i];
  16.     cin>>x>>y;
  17.     for(i=0;i<n;i++)
  18.     {
  19.         k=(y0[i]-y1[i])/(x0[i]+1e-6-x1[i]);
  20.         from=geti(x0[i],y0[i]);
  21.         to=geti(x1[i],y1[i]);
  22.         if((y-y1[i]>k*(x-x1[i]))-(x0[i]<x1[i]))swap(from,to);
  23.         for(;from!=to;to=(to+399)%400)s[to]++;
  24.     }
  25.     for(i=0;i<400;i++)
  26.         if(s[i]<n)n=s[i];
  27.     cout<<"Number of doors = "<<n+1<<endl;
  28.     return 0;
  29. }



阅读(651) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:HDUOJ 1010 Tempter of the Bone 解题报告

给主人留下些什么吧!~~