梅花桩详细分析圆内贪心思路(dfs)

问题描述

小明每天都要练功,练功中的重要一项是梅花桩。
小明练功的梅花桩排列成 n 行 m 列,相邻两行的距离为 1,相邻两列的距离也为 1。
小明站在第 1 行第 1 列上,他要走到第 n 行第 m 列上。小明已经练了一段时间,他现在可以一步移动不超过 d 的距离(直线距离)。
小明想知道,在不掉下梅花桩的情况下,自己最少要多少步可以移动到目标。

输入格式

输入的第一行包含两个整数 n, m,分别表示梅花桩的行数和列数。
第二行包含一个实数 d(最多包含一位小数),表示小明一步可以移动的距离。

输出格式

输出一个整数,表示小明最少多少步可以到达目标。

样例输入

3 4
1.5

样例输出

3

评测用例规模与约定

对于 30% 的评测用例,2 <= n, m <= 20,1 <= d <= 20。
对于 60% 的评测用例,2 <= n, m <= 100,1 <= d <= 100。
对于所有评测用例,2 <= n, m <= 1000,1 <= d <= 100。

思路:

考虑 B F S BFS BFS,将左上角坐标 ( 1 , 1 ) (1,1) (1,1)入队,令 d [ 1 ] [ 1 ] d[1][1] d[1][1] 处为0。不断将队头出队,并将与队头坐标 ( i , j ) (i,j) i,j距离 d i s < d dis<d dis<d 的所有坐标入队,并将其坐标对应的 d [ x ] [ y ] d[x][y] d[x][y] 标记为 d [ i ] [ j ] + 1 d[i][j]+1 d[i][j]+1 ,直到队列为空,此时, d [ n ] [ m ] d[n][m] d[n][m] 处即为答案。

但这并不好实现,在找与队头坐标 ( i , j ) (i,j) i,j距离 d i s < d dis<d dis<d 的所有坐标的过程中,如果搜索全图,必然TLE,所以我们要尽可能贪心地找最外围的情况,因为搜索的范围是一个圆心在左上角的 1 4 \dfrac {1}{4} 41圆,所以我们可以采用圆内贪心

先搜索圆的右边界: t y = y + ( i n t ) d ty = y + (int)d ty=y+(int)d(由于不能掉下梅花桩,我们必须取 y + ( i n t ) d y + (int)d y+(int)d为最右的边界),这肯定能到达,之后采取贪心法找边界:我们从上到下去找圆的最右边界(当然是整数点),也就是一直tx ++,但是总会有一个时刻点会超出圆的右边界,这时我们需要缩小点的横坐标,即ty --,直到满足圆内,我们继续tx ++,这样一定能找到所有最外围情况的点

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1004
int dis[N][N];
int n,m;
double d;
queue< pair<int,int> >q;
void bfs(){
    q.push(make_pair(1, 1));
    while(!q.empty()){
        pair<int,int> t = q.front(); q.pop();
        int x = t.first, y = t.second;
        int tx = x, ty = y + (int)d;//先向右移动d 
        if((n-x)*(n-x) + (m-y)*(m-y) <= d*d){
            dis[n][m] = dis[x][y] + 1;
            break;
        }
        while(tx <= n && ty >= y && ty <= m){
            if((tx - x) * (tx - x) + (ty - y) * (ty - y) <= d * d && dis[tx][ty] == 0)
                {
                    q.push(make_pair(tx, ty));
                    dis[tx][ty] = dis[x][y] + 1;
                    tx ++;
                }
                else ty --;
        }
    }
    cout<<dis[n][m]<<endl;
}
int main(){
    cin>>n>>m>>d;
    bfs();
    return 0;
}

ps.

代码部分借鉴自:蓝桥杯校内模拟赛题解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值