直线
#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
typedef struct Node
{
int A,B,C;
bool operator<(const Node&Other)const
{
return A < Other.A || (A == Other.A && B < Other.B) || (A == Other.A && B == Other.B && C < Other.C);
}
bool operator=(const Node&Other)const
{
return A==Other.A&&B==Other.B&&C==Other.C;
}
}Node;
void gcd(int& a, int& b, int &c)
{
int tmp[] = {abs(a),abs(b),abs(c)};
sort(tmp,tmp+3);
int Min =0; int idx=0;
while(Min==0)
{
Min = tmp[idx];
idx++;
}
for (int i = 2; i <= Min; i++)
{
while (a % i == 0 && b % i == 0 && c % i == 0)
{
a /= i;
b /= i;
c /= i;
}
}
}
int main()
{
set<Node> store;
for (int x1 = 0; x1 < 20; x1++)
{
for (int y1 = 0; y1 < 21; y1++)
{
for (int x2 = 0; x2 < 20; x2++)
{
for (int y2 = 0; y2 < 21; y2++)
{
if (x1 == x2 && y1 == y2) continue;
int a = y1 - y2;
int b = x1 - x2;
int c = x1 * y2 - x2 * y1;
// 化简
if (a < 0) {
a = -a;
b = -b;
c = -c;
}
if (a == 0 && b < 0) {
b = -b;
c = -c;
}
if (a == 0 && b == 0 && c < 0) {
c = -c;
}
gcd(a, b, c);
store.insert({ a, b, c });
}
}
}
}
cout << store.size() << endl;
return 0;
}
分析:
就有了思路纯暴力
核心:四重循环枚举所有两个点组合+一条直线的表达(斜截式、一般式、两点式…)+set去重
没做出来原因:
第一反应是四重循环枚举,然后觉得有点不妥(事实证明我多虑了),看一眼发现是解答题,我灵机一动应该可以手算然后直接打印答案,然后算不出来,兜兜转转回到暴力,其实也该暴力,毕竟20、21数据很小的。
然后枚举最开始想的是k、b直线然后set去重,然后double精度问题,想着怎么搞,取不同精度=判定的数量不同。最后放弃斜截式,用Ax+By+C=0的(因为A、B、C通过两个点坐标算出的表达式没有除法),然后又是化简、符号问题(2,1,3)和(-4,-2,-6)是同一条直线,然后就捏着鼻子写换符号和化简的代码(觉得比精度好解决)。然后终于写出来了。