这是去年北京赛区的B题,给出n个点,用这些点构造三角形,然后找出相似三角形个数的最大值。
昨天看这题的时候以为很难,后面发现n的范围也就18,18^3也不大,可以直接暴力做。构造三
角形的时候要注意两点:
(1)这道题会有重点,需要判重。判重时可以将点平移,然后用一个200*200的数组做标记就行了。
(2)判断三点共线,只需求出第一个与第三个点、第二个点与第三个点连线的斜率,斜率相等必然
共线。此外,处理的时候将a作为最小边、b作为中边、c作为最长边。方便判断相似。
/*Accepted 4082 0MS 416K 2343 B G++ Yu*/ #include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> using namespace std; const int MAXN = 20; const int MAXM = 820; int ans, n, d[MAXN][MAXN], m, ns; int used[210][210]; struct point { int x, y; }p[MAXN]; struct triangle { int a, b, c; }t[MAXM]; int dist(point p1, point p2)//距离的平方 { int x, y; x = p1.x - p2.x; y = p1.y - p2.y; return x * x + y * y; } bool ponls(point p0, point p1, point p2)//共线,斜率相等 { int x1, x2, y1, y2; x1 = p0.x - p2.x; y1 = p0.y - p2.y; x2 = p1.x - p2.x; y2 = p1.y - p2.y; if(x1 * y2 == x2 * y1) return true; return false; } bool similar(triangle t1, triangle t2) //相似,对应边成比例 { int a1, a2, b1, b2, c1, c2; a1 = t1.a, b1 = t1.b, c1 = t1.c; a2 = t2.a, b2 = t2.b, c2 = t2.c; if(a1 * b2 == b1 * a2 && a1 * c2 == c1 * a2 && b1 * c2 == c1 * b2) return true; return false; } void ReadGraph() { int i, j, k, s, v; n = 0; memset(used, 0, sizeof used); for(i = 1; i <= ns; i ++) { scanf("%d%d", &s, &v); s += 100, v += 100; //平移 if(used[s][v]) continue; used[s][v] = 1; p[++ n].x = s; p[n]. y = v; } for(i = 1; i <= n; i ++) for(j = 1; j <= n; j ++) d[i][j] = d[j][i] = dist(p[i], p[j]); } void MakeTriangle() { int i, j, k, temp[3]; m = 0; for(i = 1; i <= n; i ++) for(j = i + 1; j <= n; j ++) for(k = j + 1; k <= n; k ++) { if(ponls(p[i], p[j], p[k])) continue; temp[0] = d[i][j]; temp[1] = d[j][k]; temp[2] = d[i][k]; sort(temp, temp + 3); t[++ m].a = temp[0]; t[m].b = temp[1]; t[m].c = temp[2]; } } void cal() { int cnt, i, j; ans = 0; for(i = 1; i <= m; i ++) { cnt = 1; for(j = i + 1; j <= m; j ++) { if( similar(t[i], t[j])) ++ cnt; } ans = max(ans, cnt); } } int main() { while(scanf("%d", &ns), ns) { ReadGraph(); MakeTriangle(); cal(); printf("%d\n", ans); } return 0; }