题目链接:
http://codeforces.com/problemset/problem/719/C
题目大意:
小明现在得知了自己的考试成绩是一个算上小数点共n位的小数,一共有t秒时间,每秒小明都可以对自己的小数点后的成绩进行一次四舍五入,问小明最大的成绩是多少
分析:
先找到小数点位置,因为四舍五入必须从小数点后进行,然后选择最靠近小数点的一位进位,如此t次,无法进位时退出,但此做法会超时,因为每次重新找要四舍五入的下标再进行进位会消耗很多时间,所以可以在进位的同时加上判断
- 进位后当前位>9,进位到下一位
- 进位后当前位>4,如果还有时间,直接在此处继续四舍五入
- 进位后当前位<=4,成绩已无法再进位,输出结果
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include <cstdio> #include <iostream> #include <algorithm> #include <cstring>
using namespace std;
int n , t ,length; char str[200009]; char ans[200009];
bool change(int pos) { int cpos = -1; for (int i = pos ; i < length ; i ++) { if (str[i]>='5') { cpos = i-1; str[i] = '\0'; //截断后面的小数部分 length = i; break; } } int add = 1; if (cpos !=-1) //如果有可四舍五入的地方 { for (int i = cpos ; i >= 0 ; --i) { if (str[i]=='.') continue; str[i] = str[i] + add ; if (str[i]>'9') //大于9,直接进位 { str[i] = '0'; continue; } else if (str[i]>='5'&&t>0&&i>pos) //大于等于5且剩余进位次数不为0,且[当前位置在小数范围内] { --t; str[i] = '\0'; length = i; continue; } else { add = 0; break; } } if (str[length-1]=='.') { str[length-1] = '\0'; length -= 1; } if (add) { memcpy(ans+1,str,length); ans[0] = '1'; length += 1; memcpy(str,ans,length); //可能最高位在进位后>9,需要再前面再添1,由于这种情况只可能发生一次,所以两次memcpy也无妨 } return true; } else return false; }
int searchpoint() //找到小数点所在位置 { for (int i = 0 ; i < length ; i ++) if (str[i]=='.') return i+1;
} int main() { scanf("%d%d",&n,&t); scanf("%s",str); length = strlen(str); int pos = searchpoint(); while (--t>=0) { if (!change(pos)) break; } cout<<str<<endl; return 0; }
|