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;
}
原文地址:https://www.cnblogs.com/whenc/p/14007654.html