poj 1054 The Troublesome Frog

题目大意:一个r行c列的农田,有n个脚印在农田上。如果一连串脚印满足是一条直线,并且等间距分布,并且是从农田外跳入并跳出农田外,则认为这一串脚印为青蛙的一条路径。求所有路径中的最长步数,我们只关心步数大于等于3的路径。

思路:枚举两个点,构成一条直线,判断这条直线是否满足条件,若满足,则记录步数,取所有路径的步数的最大值。

几点优化和剪枝:

(1)首先将所有脚印按r从小到大排列,如果r相同,则按c从小到大排列,这是为后面的剪枝做准备。

(2)如果起点不是从农田外跳入,剪枝

(3)如果起点经过当前最大步数后已经跳出农田外,剪枝


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>

using namespace std;

struct Pos
{
    int row,column;
    bool operator< (const Pos a) const
    {
        if (a.row==row)
            return column<a.column;
        return row<a.row;
    }
}flattened_pos[5005];

bool flattened[5005][5005],is_path;
int row,column,flatten_num,ans;

int main(int argc, char** argv)
{
    int i,j,dx,dy,cnt,tmp_row,tmp_column;
    while (scanf("%d%d",&row,&column)==2)
    {
        memset(flattened,false,sizeof(flattened));
        scanf("%d",&flatten_num);
        for (i=1; i<=flatten_num; i++)
        {
            scanf("%d%d",&flattened_pos[i].row,&flattened_pos[i].column);
            flattened[flattened_pos[i].row][flattened_pos[i].column]=true;
        }
        sort(flattened_pos+1,flattened_pos+1+flatten_num);
        ans=2;
        for (i=1; i<flatten_num; i++)
        {
            for (j=i+1; j<=flatten_num; j++)
            {
                dx=flattened_pos[j].row-flattened_pos[i].row;
                dy=flattened_pos[j].column-flattened_pos[i].column;
                if (flattened_pos[i].row+(ans-1)*dx>row || flattened_pos[i].row+(ans-1)*dx<1 || flattened_pos[i].column+(ans-1)*dy>column || flattened_pos[i].column+(ans-1)*dy<1)
                    continue;
                if (flattened_pos[i].row-dx>=1 && flattened_pos[i].row-dx<=row && flattened_pos[i].column-dy>=1 && flattened_pos[i].column-dy<=column)
                    continue;
                tmp_row=flattened_pos[j].row;
                tmp_column=flattened_pos[j].column;
                is_path=true;
                for (cnt=2;; cnt++)
                {
                    tmp_row+=dx;
                    tmp_column+=dy;
                    if (tmp_row>row || tmp_row<1 || tmp_column>column || tmp_column<1)
                        break;
                    else if (flattened[tmp_row][tmp_column]==false)
                    {
                        is_path=false;
                        break;
                    }
                }
                if (is_path && cnt>ans)
                    ans=cnt;
            }
        }
        if (ans==2)
            printf("0\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值