试题 B: 直线 【第十二届蓝桥杯省赛 C/C++大学 A 组 第一场】

试题 B: 直线

本题总分:5 分
【问题描述】
在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。

给定平面上 2 × 3 个整点 {(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x ∈ Z, y ∈ Z},即横坐标是 0 到 1 (包含 0 和 1) 之间的整数、纵坐标是 0 到 2 (包含 0 和 2) 之间的整数的点。这些点一共确定了 11 条不同的直线。

给定平面上 20 × 21 个整点 {(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z},即横坐标是 0 到 19 (包含 0 和 19) 之间的整数、纵坐标是 0 到 20 (包含 0 和 20) 之间的整数的点。请问这些点一共确定了多少条不同的直线。

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

 

思路:

直线的一般式:ax+by+c=0 。因为两点能确定一条直线,故利用两层循环,让所有点两两连接构成直线,并在fun函数中判重(一条直线由一般式中的a,b,c三个参数确定,可利用一个三维数组储存这些参数)。

如:bool m[3][4][5]=true,即表示直线3x+4y+5=0已经存在了。

 

细节问题:

1,数组的下标不能是负数啊,参数如果是负数的话怎么办?

答:根据数据范围,a,b都在-20到20之间,c在-19*20到19*20=380之间,那我们记录的时候只需要给这三个参数都加上一个定值,能让最小的负数也能成正数就行了。

如:bool m[-3+50][4+50][-5+500]=true,即表示直线-3x+4y-5=0已经存在了。

 

2,怎么化简直线方程?

答:每个参数都除以(a,b,c)三个参数的绝对值 的最大公约数,用__gcd(abs(a),__gcd(abs(b),abs(c))即可

 

3,比如-2x+y+1=0和2x-y-1=0都是最简直线方程,如何判重?

答:其实很好判重,只是容易漏掉这个细节.......

 

答案:40257

代码:

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef double db;
 5 #define rep(i,a,n) for (ll i=a;i<=n;i++)
 6 #define per(i,a,n) for (ll i=n;i>=a;i--)
 7 #define Y 20
 8 #define X 19
 9 const int MAXN = 1e5 + 10;
10 const int INF = 0x3f3f3f;
11 
12 bool m[100][100][1000];
13 
14 struct node{
15     int x,y;
16 }p[MAXN];
17 
18 void fun(int x1,int y1,int x2,int y2){
19     int a=y2-y1;
20     int b=x1-x2;
21     int c=y1*x2-x1*y2;
22     int t=__gcd(abs(a),__gcd(abs(b),abs(c)));
23     //t是这三个参数的最大公约数 
24     a=a/t+50;
25     b=b/t+50;
26     c=c/t+500;
27     //设置一个定值,防止数组下标出现负数 
28     if (!m[100-a][100-b][1000-c]) 
29     //最简方程判重 
30         m[a][b][c]=true;
31 }
32 
33 int main(){
34     
35     int n=0;
36     rep(i,0,Y){
37         rep(j,0,X){
38             ++n;
39             p[n].x=j;
40             p[n].y=i;
41         }
42     }//枚举出所有的点,一共420个点 
43     
44     rep(i,1,n){
45         rep(j,1,n){
46             if(j!=i){
47                 int x1=p[i].x , y1=p[i].y;
48                 int x2=p[j].x , y2=p[j].y;
49                 fun(x1,y1,x2,y2);
50                 //直线判重 
51             }    
52         }
53     }//让所有点两两连接成直线 
54     
55     ll sum=0;//记录所有不重复的直线 的数量 
56     rep(i,0,99){
57         rep(j,0,99){
58             rep(k,0,999){
59                 if (m[i][j][k]) sum++;
60             }
61         }
62     }
63     cout<<sum;
64     return 0;
65 }
复制代码

后记:

虽然代码不是最简单的,但自认为是最简单朴素的思路,绝对人人都能理解(沾沾自喜)

posted @   NENU_南丁格尔  阅读(511)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示