POJ

题意:有个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);
}
成功的路并不拥挤,因为大部分人都在颓(笑)
原文地址:https://www.cnblogs.com/SuuT/p/8635070.html