poj 1054 The Troublesome Frog 排序后暴力枚举,剪枝优化

  一, 将C个顶点排序后枚举两点构成直线,然后求最值.  ( 排序后枚举,可减少重复枚举 )

  二, 我们枚举两点 (i, j ) ,因为我们排序后 (Xi,Yi)都比(Xj,Yj)都小,我们假定 Point(i) 作为跳进稻田路径的第一个点,

这样,我们在之后枚举到相同路径的顶点时,就无需重复计算。

  三,跳跃距离(dx,dy)向量相同,我们用 bool vis[5000][5000] 来标记合法点,当未跳出稻田且该点不合法则结束。

解题代码:

View Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;

#define MAX(a,b) (a)>(b)?(a):(b)
const int N = 5010;

struct node{
    int x, y;
    void read()
    {    scanf("%d%d",&x,&y); }
    bool operator < (node tmp) const
    {
        if(x == tmp.x) return y < tmp.y;
        return x < tmp.x;
    }
}p[N];

int n, m, C;
bool vis[N][N];

bool legal( int x, int y )
{
    if( (x >= 1) && (x <= n) && (y >= 1) && (y <= m) )
        return true;
    return false;
}
void solve()
{
    int ans = -1;
    sort( p, p+C );
    
    for(int i = 0; i < C; i++)
        for(int j = i+1; j < C; j++)
        {
            int dx = p[j].x-p[i].x;
            int    dy = p[j].y-p[i].y;
            int step = 2, x = p[j].x, y = p[j].y;    
            // 这里枚举的 I 指的是跳进稻田的入口    
            if( legal( p[i].x-dx , p[i].y-dy ) ) continue;    
            
            bool flag = true;    
            while(1)    
            {
                x += dx; y += dy;     
                if( legal( x, y ) == false ) break; // 直接跳出    
                if( !vis[x][y] ) // 未跳出且当前无点,不合法
                { flag = false; break;    }
                step++; //此时合法且未跳出,才合法    
            }    
            if( flag ) ans = MAX( ans, step );     
        }
    if( ans <= 2 ) ans = 0;
    printf("%d\n", ans );
}
int main()
{
    while( scanf("%d%d",&n,&m) != EOF)
    {
        memset(vis, 0, sizeof(vis));
        scanf("%d",&C);
        for(int i = 0; i < C; i++)
        {
            p[i].read();
            vis[ p[i].x ][ p[i].y ] = true;
        }
        solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/yefeng1627/p/2858024.html