您的位置:首页 > 其它

poj 1054The Troublesome Frog(几何——>dfs+剪枝)

2017-03-26 10:49 363 查看
In Korea, the naughtiness of the cheonggaeguri, a small frog, is legendary. This is a well-deserved reputation, because the frogs jump through your rice paddy at night, flattening rice plants. In the morning, after noting which
plants have been flattened, you want to identify the path of the frog which did the most damage. A frog always jumps through the paddy in a straight line, with every hop the same length: 


 

Your rice paddy has plants arranged on the intersection points of a grid as shown in Figure-1, and the troublesome frogs hop completely through your paddy, starting outside the paddy on one side and ending outside the paddy on the other side as shown in Figure-2: 


 

Many frogs can jump through the paddy, hopping from rice plant to rice plant. Every hop lands on a plant and flattens it, as in Figure-3. Note that some plants may be landed on by more than one frog during the night. Of course, you can not see the lines showing
the paths of the frogs or any of their hops outside of your paddy ?for the situation in Figure-3, what you can see is shown in Figure-4: 


 

From Figure-4, you can reconstruct all the possible paths which the frogs may have followed across your paddy. You are only interested in frogs which have landed on at least 3 of your rice plants in their voyage through the paddy. Such a path is said to be
a frog path. In this case, that means that the three paths shown in Figure-3 are frog paths (there are also other possible frog paths). The vertical path down column 1 might have been a frog path with hop length 4 except there are only 2 plants flattened so
we are not interested; and the diagonal path including the plants on row 2 col. 3, row 3 col. 4, and row 6 col. 7 has three flat plants but there is no regular hop length which could have spaced the hops in this way while still landing on at least 3 plants,
and hence it is not a frog path. Note also that along the line a frog path follows there may be additional flattened plants which do not need to be landed on by that path (see the plant at (2, 6) on the horizontal path across row 2 in Figure-4), and in fact
some flattened plants may not be explained by any frog path at all. 

Your task is to write a program to determine the maximum number of landings in any single frog path (where the maximum is taken over all possible frog paths). In Figure-4 the answer is 7, obtained from the frog path across row 6. 

Input
Your program is to read from standard input. The first line contains two integers R and C, respectively the number of rows and columns in your rice paddy, 1 <= R,C <= 5000. The second line contains the single integer N, the number
of flattened rice plants, 3 <= N <= 5000. Each of the remaining N lines contains two integers, the row number (1 <= row number <= R) and the column number (1 <= column number <= C) of a flattened rice plant, separated by one blank. Each flattened plant is
only listed once.

Output
Your program is to write to standard output. The output contains one line with a single integer, the number of plants flattened along a frog path which did the most damage if there exists at least one frog path, otherwise, 0.

Sample Input
6 7
14
2 1
6 6
4 2
2 5
2 6
2 7
3 4
6 1
6 2
2 3
6 3
6 4
6 5
6 7


Sample Output
7


题意:在一个矩阵方格里面,青蛙在里面跳,但是青蛙每一步都是等长的跳,从一个边界外,跳到了另一边的边界外,每跳一次对那个点进行标记。

现在给你很多青蛙跳过后的所标记的所有点,那请你从这些点里面找出一条可能的路径里面出现过的标记点最多。

一开始想枚举每一个表格内的点进行dfs+记忆化搜索,但是复杂度太大;按照点对之间的斜率关系枚举可以更加快速的定位存在的点与斜率;然后标记

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <queue>
using namespace std;
const int N = 5010;

int f

;
int n, m, cx, cy;
struct node
{
int x, y;
}p
;
int cmp(node A,node B)//按照列从小到大排序
{
if(A.y!=B.y) return A.y<B.y;
else return A.x<B.x;
}

int check(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=m) return 1;
return 0;
}

int cal(int x,int y)
{
int sum=1;
while(1)
{
if(!check(x+cx,y+cy)) break;
x=x+cx, y=y+cy;
if(f[x][y])
{
sum++;
}
else return 0;
}
return sum;
}

int main()
{

while(scanf("%d %d", &n, &m)!=EOF)
{
memset(f,0,sizeof(f));
int q;
scanf("%d", &q);
for(int i=0;i<q;i++)
{
int x, y;
scanf("%d %d", &x, &y);
f[x][y]=1;
p[i].x=x, p[i].y=y;
}
sort(p,p+q,cmp);
int ans=2;
for(int i=0;i<q;i++)
{
for(int j=i+1;j<q;j++)
{
cx=p[j].x-p[i].x, cy=p[j].y-p[i].y;
if(check(p[i].x-cx,p[i].y-cy)) continue;//如果满足,因为是按列从小到大遍历,那么一定考虑过;
if(p[i].y+ans*cy>m)break;如果最优值都超出界限,因为是按列从小到大遍历,那么其余一定也超出界限;
if(!check(p[i].x+ans*cx,p[i].y+ans*cy)) continue;因为x没有按序排列,可能不会出界;
int tmp=cal(p[i].x,p[i].y);
ans=max(ans,tmp);
}
}
if(ans<3) puts("0");
else printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: