解题报告(3)——连线游戏

标签: NOIP 基础
398人阅读 评论(1) 收藏 举报
分类:

连线游戏

题目描述

Farmer John最近发明了一个游戏,来考验自命不凡的贝茜。游戏开始的时候,FJ会给贝茜一块画着 N (2 <= N <= 200)个不重合的点的木板,其中第 i 个点的横、纵坐标分别为 X_i 和 Y_i (-1,000 <= X_i <=1,000; -1,000 <= Y_i <= 1,000)。

 

贝茜可以选两个点画一条过它们的直线,当且仅当平面上不存在与画出直线平行的直线。游戏结束时贝茜的得分,就是她画出的直线的总条数。为了在游戏中胜出,贝茜找到了你,希望你帮她计算一下最大可能得分。

 

输入格式

第 1 行: 输入 1 个正整数:N

第 2..N+1 行: 第 i+1 行用 2 个用空格隔开的整数 X_i、Y_i,描述了点 i 的坐标。

 

输出格式

输出 1 个整数,表示贝茜的最大得分,即她能画出的互不平行的直线数 。

样例数据 1

输入 

4

-1 1

-2 0

0 0

1 1

输出

4

备注

【输出说明】

贝茜能画出以下 4 种斜率的直线:-1,0,1/3 以及 1。

 

算法分析:

方法一: 暴力枚举+暴力扫描去重 期望得分:90(数据弱:100) 时间复杂度:n4(一卡常就死)

1)读入数据后,两两枚举得到全部斜率;

2)每枚举一个,搜索前面已存储的每一个,若有重复,则不加入,若没有,加入,个数加1;

3)输出个数;

 

注意:

1、由于可能会出现x[i]-x[j]=0的特殊情况,若作为除数会直接导致报错,所以要专门进行单列讨论。

2、double精度的两个数不能直接进行相等的比较一般为两数相减的绝对值小于一个极小值为相等判定,且注意精度一定要高,但是若太高可能会多解,不够高可能会少解。

 

Source:


#include
#include
#include
#include
#include
#include

using namespace std;

int n,xx,yy;
/*n:个数; xx:横坐标读入; yy:纵坐标读入*/
double x[210],y[210];
/*x:横坐标存储; y:纵坐标存储*/
double sc[40010],c;
/*sc:斜率存储; c:斜率临时存储判断*/
bool able;
/*able:判断是否已存储*/

inline void R(int &v)/*读入优化*/
{
      v=0;
      char c=0;
      bool p=true;
      while(c>'9'||c<'0')
      {
            if(c=='-')
            {
                  p=false;
            }
            c=cin.get();
      }
      while(c<='9'&&c>='0')
      {
            v=(v<<3)+(v<<1)+c-'0';
            c=cin.get();
      }
      if(p==false)
      {
            v=-v;
      }
}
 
int main(void)
{
      ios::sync_with_stdio(false);
      cin.tie(NULL);  /*cin解绑*/
      //freopen("lines.in","r",stdin);
      //freopen("lines.out","w",stdout);
      R(n);
      for(int i=1;i<=n;++i) /*读入&存储*/
      {
            R(xx);
            x[i]=xx;
            R(yy);
            y[i]=yy;
      }
      int top=0; /*个数统计*/
      for(int i=1;i<=n;++i)
      {
            for(int j=i+1;j<=n;++j)  /*枚举每一条直线*/
            {
                  if(x[i]-x[j]!=0)
                  {
                        c=(y[i]-y[j])/(x[i]-x[j]); /*计算斜率*/
                  }
                  else
                  {
                        c=10000000;  /*单独讨论除数为0的情况*/
                  }
                  int o=top;
                  for(int k=1;k<=o;++k)
                  {
                        if(abs(sc[k]-c)<0.00000000001)/*double判断是否相等*/
                        {
                              able=true; /*若相等,更改标记*/
                              break; /*跳出循环*/
                        }      
                  }
                  if(able==true)
                  {
                        able=false;
                  }
                  else
                  {
                        top++;  /*若未被存储*/
                        sc[top]=c; /*加入存储区*/
                  }
            }
      }
      cout<

方法二: 暴力枚举+stl(set)去重(代码异常简单,可以说本题为专设给set的裸题······)

1)读入数据后,两两枚举得到全部斜率;

2)每枚举一个,放入set;

3)输出set中的元素个数;

 

Source:

 

#include
#include
#include
#include
#include
#include
#include
 
using namespace std;
 
int n,xx,yy;
/*n:个数; xx:横坐标读入; yy:纵坐标读入*/
double x[210],y[210];
/*x:横坐标存储; y:纵坐标存储*/
double c;
/*c:斜率临时存储判断*/
bool able;
/*able:判断是否已存储*/
set s;
/*stl:set:可直接对加入的数据去重*/
 
inline void R(int &v) /*读入优化*/
{
      v=0;
      char c=0;
      bool p=true;
      while(c>'9'||c<'0')
      {
            if(c=='-')
            {
                  p=false;
            }
            c=cin.get();
      }
      while(c<='9'&&c>='0')
      {
            v=(v<<3)+(v<<1)+c-'0';
            c=cin.get();
      }
      if(p==false)
      {
            v=-v;
      }
}
 
int main(void)
{
      ios::sync_with_stdio(false);
      cin.tie(NULL);  /*cin解绑*/
      //freopen("lines.in","r",stdin);
      //freopen("lines.out","w",stdout);
      R(n);
      for(int i=1;i<=n;++i) /*读入&存储*/
      {
            R(xx);
            x[i]=xx;
            R(yy);
            y[i]=yy;
      }
      for(int i=1;i<=n;++i)  /*枚举每一条直线*/
      {
            for(int j=i+1;j<=n;++j)
            {
                  if(x[i]-x[j]!=0)
                  {
                        c=(y[i]-y[j])/(x[i]-x[j]); /*计算斜率*/
                  }
                  else
                  {
                        c=10000000; /*单独讨论除数为0的情况*/
                  }
                  s.insert(c); /*插入set*/
            }
      }
      cout<


方法三: 暴力枚举+快速排序+去重

1)读入数据后,两两枚举得到全部斜率;

2)每枚举一个,放入存储空间;

3)快速排序使相同斜率相邻;

4)手动去重;

 

Source:

 

无,只需在第一种后面加上sort排序即可;


Summary:

本题其实并不算难,但是却需要考虑一些琐碎问题,所以编写过程中一定要考虑全面,并且对于我们已有的stl也要有所了解,必要时可以使用来简化编写和运算。以上三种方法中,明显就是用set的算法最为简单。

查看评论

【连线游戏】解题报告

1.连线游戏 【问题描述】   佳佳最近发明了一个游戏,来考验自命不凡的津津。游戏开始的时候,佳佳会给津津一块画着N (2 ...
  • wu_yihao
  • wu_yihao
  • 2011-10-31 20:19:37
  • 552

NOIP2008 普及组T3 传球游戏 解题报告-S.B.S.

题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起做传球游戏。 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每...
  • SBS2000
  • SBS2000
  • 2016-05-02 16:44:20
  • 766

JavaScript游戏之连连看连线算法实例

JavaScript游戏之连连看连线算法实例
  • qq_32319583
  • qq_32319583
  • 2016-11-24 21:07:39
  • 809

连线游戏Game of Lines

以后,如果不是A+B问题,我尽量每题都写,聚沙成塔 1610: [Usaco2008 Feb]Line连线游戏 Time Limit: 5 Sec  Memory Limit: 64 MB Sub...
  • The_Great_Prc
  • The_Great_Prc
  • 2017-04-03 17:20:43
  • 201

对战游戏源码

  • 2017年10月16日 14:43
  • 1.48MB
  • 下载

HNOI2011解题报告

HNOI2011解题报告
  • XY20130630
  • XY20130630
  • 2017-05-19 21:12:02
  • 652

【模拟 计算几何】连线游戏 lines.pas/c/cpp

连线游戏 lines.pas/c/cpp 【题目描述】 Farmer John最近发明了一个游戏,来考验自命不凡的贝茜。游戏开始的时候,FJ会给贝茜一块画着N (2    贝茜可以选两个点画...
  • jiangzh7
  • jiangzh7
  • 2012-11-06 18:40:43
  • 815

九宫格游戏java实现

  • 2012年07月18日 15:31
  • 7KB
  • 下载

连线游戏

时限:1000ms 内存限制:10000K  总时限:3000ms描述:Farmer John最近发明了一个游戏,来考验自命不凡的贝茜。游戏开始的时候,FJ会给贝茜一块画着N (2 贝茜可以选两个点画...
  • Shimizu_Masato
  • Shimizu_Masato
  • 2011-06-21 21:42:00
  • 312

连线消失游戏源码2012929

  • 2012年09月29日 16:45
  • 154KB
  • 下载
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 2万+
    积分: 2169
    排名: 2万+
    博客专栏
    最新评论