题目链接:http://bailian.openjudge.cn/practice/2812/
分析:
两点决定一条直线,选取任意两个被踩踏的水稻,判断其是否能构成横跨稻田的直线,并计算在这条直线上的被踩踏的水稻数量;
代码:
#include <cstdio>
#include <algorithm>
using namespace std;
struct Plant{
int x,y;
bool operator < (const Plant & b)const{
if(x == b.x)return y < b.y;
return x < b.x;
}
};
Plant nodes[5002];
bool map[5002][5002];
int main(){
int r,c,n;
scanf("%d%d",&r,&c);
scanf("%d",&n);
for(int i = 0;i < n;i++){
int x,y;
scanf("%d%d",&x,&y);
map[x][y] = 1;
nodes[i].x = x;
nodes[i].y = y;
}
sort(nodes,nodes+n);
int maxL = 0;
for(int i = 0;i < n-1;i++)
for(int j = i + 1;j < n;j++){
int tempL = 2;
Plant p1 = nodes[i];
Plant p2 = nodes[j];
int d1 = p2.x - p1.x;
int d2 = p2.y - p1.y;
if(p1.x - d1 > 0 && p1.x - d1 <= r && p1.y - d2 > 0 && p1.y - d2 <= c)continue;
if(p1.x + maxL * d1 > r)break; //所得直线不会比现在最大长度长,并且因为排好序的nodes x递增,所以直接break
if(p1.y + maxL * d2 > c || p1.y + maxL * d2 <= 0)continue; //所得直线不会比现在最大长度长
int x,y;
for(x = p2.x + d1,y = p2.y + d2;x <= r && y <= c && x > 0 && y > 0;x += d1,y += d2)
if(map[x][y] == 1)tempL++;
else break;
if(x > 0 && x <= r && y > 0 && y <= c)continue; //如果没有横跨过稻田,则不进行比较,直接跳过
/*向另一个方向遍历,看是否能横跨稻田。
* 可以通过 "if(p1.x - d1 > 0 && p1.x - d1 <= r && p1.y - d2 > 0 && p1.y - d2 <= c)continue;"剪枝
for(x = p1.x - d1,y = p1.y - d2;x <= r && y <= c && x > 0 && y > 0;x -= d1,y -= d2)
if(map[x][y] == 1)tempL++;
else break;
if(x > 0 && x <= r && y > 0 && y <= c)continue;
*/
if(tempL > maxL){
maxL = tempL;
}
}
if(maxL >= 3)
printf("%d",maxL);
else
printf("0");
}