http://poj.org/problem?id=1054
题意:
给你r*c的一块稻田,每个点都种有水稻,青蛙们晚上会从水稻地里穿过并留下脚印,问题确保青蛙的每次跳跃的长度想相同,而且沿直线行走,给出n个青蛙的脚印点问存在大于等于3的最大青蛙走的连续的脚印个数;若不存在输出0
思路:
这题O(n^3)的三次方+j剪枝竟然能过无语了。。。。首先排序,然后O(n^2)枚举任意两点找直线,O(n^2)判断同一直线并且是同一青蛙留下的脚印然后求最大值。
剪枝:
1:青蛙的起点肯定在稻田外;2:该点的直线上的脚印一定要大于上一次的点数;3:多余上一点的基础上点要在稻田内;
#include <iostream> #include <cmath> #include <cstdio> #include <cstring> #include <algorithm> #define maxn 5007 #define N 8 using namespace std; const int inf = 99999999; struct node { int x,y; }p[maxn]; int map[maxn][maxn]; int n,r,c; int cmp(node a,node b) { if (a.x != b.x) return a.x < b.x; else return a.y < b.y; } bool inMap(int x,int y) { if (x > 0 && x <= r && y > 0 && y <= c) return true; else return false; } int getS(int x,int y,int dx,int dy) { int sum = 0; while (inMap(x,y)) { if (!map[x][y]) return 0;//注意这里一定要返回0,因为这里错了好多次 //首先如果我们发现青蛙的路径一定在最后走出稻田的,如果在找点的时候 //还为走出稻田就发现不存在的点了,就说明我们找的不是青蛙正确的路径 //而可能是多条路径交叉所得,所以一定要返回0 sum++; x += dx; y += dy; } return sum; } int main() { //freopen("d.txt","r",stdin); int i,j; while (~scanf("%d%d",&r,&c)) { scanf("%d",&n); memset(map,0,sizeof(map)); for (i = 0; i < n; ++i) { scanf("%d%d",&p[i].x,&p[i].y); map[p[i].x][p[i].y] = 1; } sort(p,p + n,cmp); int ans = 2; for (i = 0; i < n; ++i) { for (j = i + 1; j < n; ++j) { int dx = p[j].x - p[i].x; int dy = p[j].y - p[i].y; if (p[i].x + ans*dx > r || p[i].y + ans*dy > c) continue;//剪枝1 if (inMap(p[i].x - dx,p[i].y - dy)) continue;//剪枝2 if (!inMap(p[i].x + ans*dx,p[i].y + ans*dy)) continue;//剪枝3 ans = max(ans,getS(p[i].x,p[i].y,dx,dy)); } } if (ans < 3) printf("0\n"); else printf("%d\n",ans); } return 0; }