Codeforces 520B (bfs,dp,dfs,greedy)

本文介绍了解决从一个整数转换到另一个整数的最短步骤问题的四种算法实现方法,包括动态规划(DP)、深度优先搜索(DFS)、贪心算法及广度优先搜索(BFS)。通过对比不同算法的优缺点,帮助读者理解每种方法的适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

做法一,入门级dp,转移方程:

dp[i] = min(dp[i],dp[i/2]+1,dp[i+1]+1); //i为偶数
dp[i] = min(dp[i],dp[i+1]+1);//i为奇数

由于转移方程涉及两个方向,故选用类似于冒泡排序的while套for双重循环

#include <cstdio>
#include <algorithm>

using namespace std;

#define maxn 10050

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int len = max(n,m*2);
    int dp[maxn*2];
    for(int i=0;i<len+1;i++) dp[i] = maxn;
    dp[n] = 0;

    bool flag = true;
    while(flag)
    {
        flag = false;
        for(int i=len-1;i>0;i--)
            if(dp[i] > dp[i+1] + 1)
            {
                flag = true;
                dp[i] = dp[i+1] +1;
            }
        for(int i=2;i<len+1;i+=2)
            if(dp[i] > dp[i/2]+1)
            {
                flag = true;
                dp[i] = dp[i/2]+1;
            }
    }
    printf("%d\n",dp[m]);
    return 0;
}


做法二,入门级dfs,需要加入数组来剪枝:

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

#define maxn 10050

int ans[maxn*2];

void dfs(int loc,int key,int step)
{
    if(loc<=0) return ;
    if(step>ans[loc]) return ;
    ans[loc] = step;

    if(loc > key){dfs(key,key,step+loc-key);return ;}
    if(loc == key){ans[key] = min(ans[key],step);return ;}

    dfs(loc-1,key,step+1);
    dfs(loc*2,key,step+1);
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    memset(ans,0,sizeof(ans));
    for(int i=0;i<max(n,m*2)+1;i++) ans[i] = maxn;
    ans[n] = 0;

    dfs(n,m,0);
    printf("%d\n",ans[m]);
    return 0;
}

做法三,贪心,逆向思维,若m/2或(m+1)/2大于n时,先采用除2:

#include <cstdio>
#include <algorithm>

using namespace std;

#define maxn 10050

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    if(n>=m)
    {
        printf("%d\n",n-m);
        return 0;
    }
    int ans=0;
    while(m>0)
    {
        if(m&1)
        {
            ans++;
            m = m+1;
        }
        if(m/2 <= n)
        {
            printf("%d\n",ans+1+n-m/2);
            return 0;
        }else
        {
            ans++;
            m = m/2;
        }
    }
    return 0;
}


做法四,bfs

区间DP是一种动态规划的方法,用于解决区间范围内的问题。在Codeforces竞赛中,区间DP经常被用于解决一些复杂的字符串或序列相关的问题。 在区间DP中,dp[i][j]表示第一个序列前i个元素和第二个序列前j个元素的最优解。具体的转移方程会根据具体的问题而变化,但是通常会涉及到比较两个序列的元素是否相等,然后根据不同的情况进行状态转移。 对于区间长度为1的情况,可以先进行初始化,然后再通过枚举区间长度和区间左端点,计算出dp[i][j]的值。 以下是一个示例代码,展示了如何使用区间DP来解决一个字符串匹配的问题: #include <cstdio> #include <cstring> #include <string> #include <iostream> #include <algorithm> using namespace std; const int maxn=510; const int inf=0x3f3f3f3f; int n,dp[maxn][maxn]; char s[maxn]; int main() { scanf("%d", &n); scanf("%s", s + 1); for(int i = 1; i <= n; i++) dp[i][i] = 1; for(int i = 1; i <= n; i++) { if(s[i] == s[i - 1]) dp[i][i - 1] = 1; else dp[i][i - 1] = 2; } for(int len = 3; len <= n; len++) { int r; for(int l = 1; l + len - 1 <= n; l++) { r = l + len - 1; dp[l][r] = inf; if(s[l] == s[r]) dp[l][r] = min(dp[l + 1][r], dp[l][r - 1]); else { for(int k = l; k <= r; k++) { dp[l][r] = min(dp[l][r], dp[l][k] + dp[k + 1][r]); } } } } printf("%d\n", dp[n]); return 0; } 希望这个例子能帮助你理解区间DP的基本思想和应用方法。如果你还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值