PAT 顶级 1034 Number Game - BFS/DP

原题链接

https://pintia.cn/problem-sets/994805148990160896/exam/problems/1697152161245261825?type=7&page=0

题目大意

给定三个整数 A , B , N A,B,N A,B,N,目标是从 A A A开始变成 B B B,其中每一步从以下三种变化方法中选择一个:(现在的数字是 X X X
( 1 ) X = X + 1 (1) X = X+1 (1)X=X+1
( 2 ) X = X − 1 (2)X = X-1 (2)X=X1
( 3 ) X = X × n (3)X = X\times n (3)X=X×n
求最小的变化次数。

数据范围

− 1 0 5 < = A , B < = 1 0 5 -10^5 <= A,B <= 10^5 105<=A,B<=105
1 < N < 10 1 < N < 10 1<N<10

题解

非常简单的BFS题,利用一个队列进行BFS,用一个数组记录步骤数。从 A A A出发,起始时将 A A A压入队列。假设某一时刻队列头的元素是 X X X,达到 X X X所需要的步骤数是 i i i,下一步可以到达的数字是 X + 1 , X − 1 , X × N X+1,X-1,X\times N X+1X1X×N,这三个数字如果之前已经访问过,则不再压入队列,否则压入队列且步骤数即为 i + 1 i+1 i+1,持续进行类似操作直到选择到 B B B即可。
唯一需要注意的是,需要卡住数字的上下界,否则会有数组越界或超时的问题。当目前的 X X X足够大的时候,就没有必要继续向上乘。我们也不需要严谨地证明这个上界是多少,我做题的时候这个 X X X的范围以 1 0 5 10^5 105向上下各偏差 200000 200000 200000为界限都足以通过本题。由于B可能有负数,整体加一个偏移量即可。

AC代码

#include <bits/stdc++.h>
using namespace std;
int bias = 300000;
int main()
{
    int t;
    cin >> t;
    while(t--){
        int f[600050] = {0};
        memset(f,0x3f,sizeof f);
        int a,b,n;
        cin >> a >> b >> n;
        f[bias+a] = 0;
        queue<int> q;
        q.push(bias + a);
        while(q.front() != bias + b){
            int u = q.front();
            if(u<500000) {
                if(f[u+1] > f[u] + 1){
                    f[u+1] = f[u] + 1;
                    q.push(u+1);
                }
            }
            if(u>100000) {
                if(f[u-1] > f[u] + 1){
                    f[u-1] = f[u] + 1;
                    q.push(u-1);
                }
            }
            u -= bias;
            if(u*n + bias >= 100000 && u*n + bias <= 500000){
                if(f[u*n+bias] > f[u+bias] + 1){
                    f[u*n+bias] = f[u+bias] + 1;
                    q.push(u*n + bias);
                }
            }
            q.pop();
        }
        cout << f[b+bias] << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值