您的位置:首页 > 其它

POJ 1054 The Troublesome Frog(dp+剪枝)

2014-06-01 13:05 483 查看
题意:好多青蛙祸害庄稼,已知一个R*C的稻田。给出被青蛙踩到的庄稼的坐标,已知一只青蛙的跳跃距离是一定的,它从稻田外踩过稻田中的M个点然后又跳出稻田,求某只青蛙踩出的M最大值。(也就是说一只青蛙可以踩出一条线来。)小于三的情况直接输出0;

先按x排序,如果x相等按y排序,然后枚举两个点确定一条直线(这两个点在直线上是相邻的),然后找这条直线上共有多少个这样的点(两相邻点的距离相同。)

已知枚举出i,j点(i为起点);

dx = p[j].x - p[i].x;

dy = p[j].y - p[i].y;

设ans为之前求出的最优值(这里体现出dp的思想)

剪枝:

1、如果p[i].x + ans*dx > R,则跳出这次对j的枚举;

2、如果(p[i].x - dx, p[i].y - dy)在棋盘内,剪枝;

3、如果(p[i].x + ans*dx, p[i].y + ans*dy)不再棋盘内,剪枝;

The Troublesome Frog

Time Limit: 5000MS Memory Limit: 100000K
Total Submissions: 10089 Accepted: 3021
Case Time Limit: 500MS
Description

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

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-7
#define M 1000100
///#define LL __int64
#define LL long long
#define INF 0x3fffffff
#define PI 3.1415926535898

using namespace std;

const int maxn = 5005;

struct node
{
int x, y;
}f[maxn];

bool mp[maxn][maxn];
int r, c, n;

bool cmp(node a, node b)
{
if(a.x == b.x)
return a.y < b.y;
return a.x < b.x;
}

bool judge(int x, int y)
{
if(1 <= x && x <= r && 1 <= y && y <= c)
return true;
return false;
}

int cnt(int x, int y, int dx, int dy)
{
int ans = 0;
while(judge(x, y))
{
if(!mp[x][y])
return 0;
ans++;
x += dx;
y += dy;
}
return ans;
}

int main()
{
while(cin >>r>>c>>n)
{
for(int i = 0; i <= r; i++)
for(int j = 0; j <= c; j++)
mp[i][j] = false;
for(int i = 0; i < n; i++)
{
cin >>f[i].x>>f[i].y;
mp[f[i].x][f[i].y] = true;
}
sort(f, f+n, cmp);
int ans = 2;
for(int i = 0; i < n-1; i++)
{
for(int j = i+1; j < n; j++)
{
int dx = f[j].x-f[i].x;
int dy = f[j].y-f[i].y;
int tx = f[i].x + ans*dx;
int ty = f[i].y + ans*dy;
if(tx > r)//剪枝,看改点是否有搜索的意义(tx>r)说明不会有点比ans还大
break;
if(judge(f[i].x-dx, f[i].y-dy))//剪枝,看起点是否在外面
continue;
if(!judge(tx, ty))//剪枝,终点是否出界
continue;
int tmp = cnt(f[i].x, f[i].y, dx, dy);
ans = max(tmp, ans);
}
}
if(ans < 3)
cout<<0<<endl;
else
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: