zoukankan      html  css  js  c++  java
  • ABC155E

    简述题意,给你一个大数,你可以选择10的次幂进行加减运算,问如何用最少的次数从0到达这个大数

    考虑从这个大数到0,从最低位开始,每次都将这个位置取完,2种策略,贪心的话不好处理进位的情况,可以想到是DP

    设dp[i][0]为取到第i位,将第i位直接拿完的最小次数,dp[i][1]为取到第i位,进位后拿完的最小次数,可以得到状态转移,num表示第i位的数字

    dp[i][0] = min(dp[i-1][0], dp[i-1][1]+1) + num,dp[i-1][1]-1表示进了一位,所以第i位就要+1

    dp[i][1] = 10 - num + min(dp[i-1][0], dp[i-1][1]-1)  同理,dp[i-1][1]进了一位,num相当于(num+1), 10-(num+1) = 10 - num - 1

    注意初始化状态,最终取答案的时候要在最高位的下一位统计,因为最高位可能也进位了,相当于放了一个虚0

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) ((x)&(-x))
    typedef long long LL;
    
    const int maxm = 1e6+5;
    int dp[maxm][2];
    
    void run_case() {
        string str;
        cin >> str;
        dp[str.size()-1][1] = str[str.size()-1]-'0';
        dp[str.size()-1][0] = 10 - str[str.size()-1] +'0';
        for(int i = str.size()-2; i >= 0; --i) {
            int num = str[i]-'0';
            dp[i][1] = min(dp[i+1][0]+1, dp[i+1][1]) + num;
            dp[i][0] = 10 - num + min(dp[i+1][0]-1, dp[i+1][1]);
        }
        cout << min(dp[0][0]+1, dp[0][1]);
        
    }
    
    int main() {
        ios::sync_with_stdio(false), cin.tie(0);
        //cout.setf(ios_base::showpoint);cout.precision(8);
        run_case();
        cout.flush();
        return 0;
    }
    View Code

    我们也可以从最高位开始,dp函数的意义相同,只是状态转移的部分不一样

    dp[i][0] = min(dp[i+1][0], dp[i+1][1]) + num

    dp[i][1] = 10 - num + min(dp[i+1][0]+1, dp[i+1][1]-1) 第i位进位了,所以dp[i+1][0]要+1, 进了位dp[i+1][1]要-1

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) ((x)&(-x))
    typedef long long LL;
    
    const int maxm = 1e6+5;
    int dp[maxm][2];
    
    void run_case() {
        string str;
        cin >> str;
        dp[0][0] = str[0] - '0';
        dp[0][1] = 10 - str[0] + '0' + 1;
        for(int i = 1; i < str.size(); ++i) {
            int num = str[i] - '0';
            dp[i][0] = min(dp[i-1][0], dp[i-1][1]) + num;
            dp[i][1] = 10 - num + min(dp[i-1][0]+1, dp[i-1][1]-1);
        }
        cout << min(dp[str.size()-1][0], dp[str.size()-1][1]);
    }
    
    int main() {
        ios::sync_with_stdio(false), cin.tie(0);
        //cout.setf(ios_base::showpoint);cout.precision(8);
        run_case();
        cout.flush();
        return 0;
    }
    View Code

    注意代码中的i+1与i-1是相反的,因为字符串读入下标是反的

     该题的母题应该是cf gym的一套题

    ArabellaCPC 2019 J. Thanos Power

  • 相关阅读:
    JAVA基础补漏--文件读取
    JAVA-Lambda表达式
    JAVA基础补漏--可变参数
    JAVA基础补漏--SET
    Apache ab 测试结果的分析
    同源策略和跨域问题
    php curl 伪造IP来源的实例代码
    HTTP状态码详解
    PHP 根据IP地址获取所在城市
    MySQL MERGE存储引擎 简介及用法
  • 原文地址:https://www.cnblogs.com/GRedComeT/p/12323390.html
Copyright © 2011-2022 走看看