1. 程式人生 > 實用技巧 >CF718A Efim and Strange Grade(貪心)題解

CF718A Efim and Strange Grade(貪心)題解

演算法

貪心+無數有趣的細節

高能預警:本題細節較多,請仔細食用。

思路

從小數點往後搜,直到遇見第一個\(\geq 5\)的數字,它就是我們要四捨五入的第一個。然後從它開始往回搜,只要\(\geq 5\)就四捨五入。

正確性

小數點後位數靠前的數字越大,值越大,所以我們將第一個能“\(5\)入”的點“入”掉(因為這樣才能使得“入”過去的\(1\)價值最大)。

那為什麼往回搜的時候能入則入呢?

  • 因為往回搜的數必然是小於\(5\)的,只有當前的數往前進了位才有可能\(\geq 5\),所以我們只能給當前數進位(如果它可以)。

細節

  • 整數位上不能四捨五入(但可以進位)!
  • 小數位與整數位的進位要分開處理!
  • 可能出現一個也不能進的情況!
  • 整數的最高位有可能進\(1\)! (如:\(99.459\)
  • 記得判斷沒有小數點的情況!

大概就這麼多了……

參考程式碼

/*
 * @Author: When_C 
 * @Date: 2020-11-19 19:29:11 
 * @Last Modified by: When_C
 * @Last Modified time: 2020-11-19 19:49:45
 */
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 2e5 + 10;
int n,t,a[maxn],top;
char c[maxn];

int main(){
    scanf("%d%d%s", &n, &t, c + 1);
    int loc,pos = -1;
    for(int i = 1; i <= n; ++ i){
        if(c[i] >= '0' && c[i] <= '9') a[++top] = c[i] - '0';
        else loc = top + 1;
    }
    for(int i = loc; i <= top; ++ i)
        if(a[i] >= 5){pos = i; break;}
    if(pos > 0){
        int pre = 1; pos -= 1; t -= 1;
        for(int i = pos; i >= 1; -- i){
            if(!pre && (!t || i < loc)) break;
            a[i] += pre; pre = 0;
            if(a[i] > 10) pre = 1, a[i] %= 10;
            if(a[i] == 10){
                pre = 1; a[i] %= 10;
                if(i >= loc) pos -= 1;
            } 
            if(a[i] >= 5 && t && i >= loc) pre += 1, pos -= 1, t--;
        }
        if(pre) a[0] = 1;
    }
    if(a[0]) printf("%d", a[0]);
    for(int i = 1; i <= pos; ++ i){
        printf("%d", a[i]);
        if(i == loc - 1 && i != pos) printf(".");
    }
    if(pos < 0) printf("%s", c + 1);
    return 0;
}