题意:有个R*C的格网。上面有若干个点,这些点可以连成一些直线,满足:这些点在直线上均匀排布(也就是间隔相等),直线的两段穿过网格(也就是第一个,最后一个在网格的边界附近)
求某条直线上最多的点数
题解:先排序,再任取两个水稻,算出之间的dx,dy,然后就能推出前后的水稻坐标,用如果满足路径上一直有水稻(用binarysearch),且第一个点与最后一个点在水稻外面,就是一个可行的解,维护其最大值。
注意一些判断。
ac代码:
#include<iostream> #include<algorithm> #define _for(i,a,b) for(int i=(a);i<(b);i++) using namespace std; const int maxn = 5e3 + 5; struct plant { int x, y; bool operator <(const plant b)const { return this->x == b.x ? this->y < b.y : this->x < b.x; } //bool operator ==(const plant b)const { return this->x == b.x&&this->y == b.y; } }p[maxn]; int c, r; int n; int dx, dy, px, py,mx=2,steps; int searchPath(plant p1, int dx, int dy) { plant dp; dp.x = p1.x + dx; dp.y = p1.y + dy; int steps =2; while (dp.x <= r&&dp.x >= 1 && dp.y <= c&&dp.y >= 1) { if (!binary_search(p, p + n, dp)) {steps = 0; break;} dp.x += dx; dp.y += dy; steps++; } return steps; } int main() { cin >> r >> c; cin >> n; _for(i, 0, n) { cin >> p[i].x >> p[i].y; } sort(p, p + n); _for(i, 0, n - 2)_for(j, i + 1, n - 1) { dx = p[j].x - p[i].x; dy = p[j].y - p[i].y; px = p[i].x -dx; py = p[i].y -dy; if (px <= r&&px >= 1 && py <= c&&py >= 1)continue; if (p[i].x + (mx - 1)*dx > r)break;//已经是最小dx了,这都不满足,直接换第一个点 if (p[i].y + (mx - 1)*dy > c|| p[i].y + (mx - 1)*dy < 1)continue;//dy并不递增,也可能小于0 steps = searchPath(p[j], dx, dy); mx = max(mx, steps); } cout << (mx == 2 ? 0:mx); }