zoukankan      html  css  js  c++  java
  • AtCoder ABC 155E Payment

    题目链接:https://atcoder.jp/contests/abc155/tasks/abc155_e

    题目大意

      有$10^{100}+1$种面值的钞票($1, 10, 10^2, 10^3, dots, 10^{10^{100}}$),现在有一个价值为$N$的商品,为了买到这个商品,你将付给商家一些钞票,而商家可能会找你一些钞票(如果你实际付款大于$N$的话),请问最少需要多少张钞票即可完成这次交易呢?

    分析1(DP)

      拿个位举例,假设个位为$X$,那么付清个位只有两种付法,第一种是付$X$张面值为$1$的钞票;第二种是先付一张面值为$10$的钞票,商家再找$10 - X$张面值为$1$的钞票。其余位同理,不同的是,在考虑高位时,如果高位的低一位采取了第二种付法,高位上的数应当加一。以$N = 67$为例,先只使用$1$元钞票搞定$7$元,我先付$10$元,商家再退$3$元,此时$N = 60$,但是我用了一张$10$元钞票,所以商家再退$10$元给我,这样$N = 70$,可以看到,采用第二种策略后十位进了一位,而个位数消耗的钞票为$10 - 7 = 3$张。
      由此可以很容易想到可以用DP做,设$X(i) = N \% 10^{i + 1}, 0 leq i$,设$Y(i)$为$N$从右往左数第$i$个数字,定义$dp[i][0/1]$为$X(i)$的最高位再第一/第二种策略下的最优解,那么状态转移方程即为:

      $$
        egin{align*}
        dp[i][0] &= min(Y(i) + dp[i - 1][0], Y(i) + dp[i - 1][1]) \
        dp[i][1] &= min(1 + 10 - Y(i) + dp[i - 1][0], 1 + 10 - (Y(i) + 1) + dp[i - 1][1] - 1)
        end{align*}
      $$

    代码如下

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 /*-------------------Define Start-------------------*/
     5 typedef bool BL;                        // 布尔类型
     6 typedef char SB;                        // 有符号1字节,8位
     7 typedef unsigned char UB;                // 无符号1字节,8位
     8 typedef short SW;                        // 有符号短整型,16位
     9 typedef unsigned short UW;                // 无符号短整型,16位
    10 typedef long SDW;                        // 有符号整型,32位
    11 typedef unsigned long UDW;               // 无符号整型,32位
    12 typedef long long SLL;                    // 有符号长整型,64位
    13 typedef unsigned long long ULL;            // 无符号长整型,64位
    14 typedef char CH;                        // 单个字符
    15 typedef float R32;                        // 单精度浮点数
    16 typedef double R64;                        // 双精度浮点数
    17 
    18 #define Rep(i, n) for (register SDW i = 0; i < (n); ++i)
    19 #define For(i, s, t) for (register SDW i = (s); i <= (t); ++i)
    20 #define rFor(i, t, s) for (register SDW i = (t); i >= (s); --i)
    21 #define foreach(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
    22 #define ms0(a) memset(a,0,sizeof(a))
    23 #define msI(a) memset(a,0x7f,sizeof(a))
    24 #define LOWBIT(x) ((x)&(-x))
    25 
    26 #define MP make_pair
    27 #define PB push_back
    28 #define ft first
    29 #define sd second
    30 #define ALL(x) x.begin(),x.end()
    31 
    32 #define pr(x) cout << #x << " = " << x << "  "
    33 #define prln(x) cout << #x << " = " << x << endl
    34 
    35 const ULL mod = 1e9 + 7;                //常用模数(可根据题目需要修改)
    36 const ULL inf = 0x7fffffff;                //用来表示无限大
    37 const ULL infLL = 0x7fffffffffffffffLL;    //用来表示无限大
    38 /*-------------------Define End-------------------*/
    39 
    40 const UDW maxN = 1e6 + 7;
    41 string N;
    42 SDW dp[maxN][2]; 
    43 SDW ans;
    44 
    45 void input(){
    46     cin >> N;
    47 }
    48 
    49 void solve(){
    50     dp[1][0] = N[N.size() - 1] - '0';
    51     dp[1][1] = 11 - N[N.size() - 1] + '0'; 
    52     
    53     For(i, 2, N.size()) {
    54         SDW Y = N[N.size() - i] - '0';
    55 
    56         dp[i][0] = min(Y + dp[i - 1][0], Y + dp[i - 1][1]);
    57         dp[i][1] = min(1 + 10 - Y + dp[i - 1][0], 1 + 10 - (Y + 1) + dp[i - 1][1] - 1);
    58     }
    59     
    60     ans = min(dp[N.size()][0], dp[N.size()][1]);
    61 }
    62 
    63 void output(){
    64     cout << ans << endl;
    65 }
    66 
    67 int main() {
    68     input();
    69     solve();
    70     output();
    71     return 0;
    72 }
    View Code

    分析2(贪心)

      再以个位为例,当个位小于5时,采取第一种策略一定是最优的,而当个位大于5时,采取第二种策略则一定是最优的(即使算上进位对于十位数的影响)。只有当个位等于5时,两种策略的个位收益一致,这时候就要看进位对于十位数的影响了,如果十位数进位后小于5,那就选第一种策略,如果大于5,应该选第二种,等于5,随意。(对于贪心的证明,实在不知道咋证,反正程序是对的。。。)

    代码如下

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 /*-------------------Define Start-------------------*/
     5 typedef bool BL;                        // 布尔类型
     6 typedef char SB;                        // 有符号1字节,8位
     7 typedef unsigned char UB;                // 无符号1字节,8位
     8 typedef short SW;                        // 有符号短整型,16位
     9 typedef unsigned short UW;                // 无符号短整型,16位
    10 typedef long SDW;                        // 有符号整型,32位
    11 typedef unsigned long UDW;               // 无符号整型,32位
    12 typedef long long SLL;                    // 有符号长整型,64位
    13 typedef unsigned long long ULL;            // 无符号长整型,64位
    14 typedef char CH;                        // 单个字符
    15 typedef float R32;                        // 单精度浮点数
    16 typedef double R64;                        // 双精度浮点数
    17 
    18 #define Rep(i, n) for (register SDW i = 0; i < (n); ++i)
    19 #define For(i, s, t) for (register SDW i = (s); i <= (t); ++i)
    20 #define rFor(i, t, s) for (register SDW i = (t); i >= (s); --i)
    21 #define foreach(i, c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
    22 #define ms0(a) memset(a,0,sizeof(a))
    23 #define msI(a) memset(a,0x7f,sizeof(a))
    24 #define LOWBIT(x) ((x)&(-x))
    25 
    26 #define MP make_pair
    27 #define PB push_back
    28 #define ft first
    29 #define sd second
    30 #define ALL(x) x.begin(),x.end()
    31 
    32 #define pr(x) cout << #x << " = " << x << "  "
    33 #define prln(x) cout << #x << " = " << x << endl
    34 
    35 const ULL mod = 1e9 + 7;                //常用模数(可根据题目需要修改)
    36 const ULL inf = 0x7fffffff;                //用来表示无限大
    37 const ULL infLL = 0x7fffffffffffffffLL;    //用来表示无限大
    38 /*-------------------Define End-------------------*/
    39 
    40 const UDW maxN = 1e6 + 7;
    41 string N;
    42 SLL ans;
    43 
    44 void input(){
    45     cin >> N;
    46     N = "0" + N; 
    47 }
    48 
    49 void solve(){
    50     rFor(i, N.size() - 1, 0) {
    51         SLL x = N[i] - '0';
    52         
    53         if(x > 5 || x == 5 && N[i - 1] >= '5') {
    54             ans += 10 - x;
    55             ++N[i - 1];
    56         }
    57         else {
    58             ans += x;
    59         }
    60     }
    61 }
    62 
    63 void output(){
    64     cout << ans << endl;
    65 }
    66 
    67 int main() {
    68     input();
    69     solve();
    70     output();
    71     return 0;
    72 }
    View Code
  • 相关阅读:
    install kde in ubuntu
    Upgrade to or Install Cinnamon 2.4 in Ubuntu
    enjoy dollar vs cash dollar
    opencv linux
    高频交易都有哪些著名的算法
    wpf
    opencv mat flags含义
    gphoto2 canon eos450d
    gphoto2
    task optimization之superglue分析
  • 原文地址:https://www.cnblogs.com/zaq19970105/p/12339997.html
Copyright © 2011-2022 走看看