题目: 传送门
思路: 我们先从一个例子 99.4492349入手,如果我们T= 1 ,我们应该是在小数点后第3位 四舍五入,结果为99.45,我们会发现如果前面有可以直接 进位的值,那我们应该是优先在这个位置 舍入 而不是后面的,因为在该位置进位一定比在后面位置进位更优。
如果 t >= 2,我们还是看上面那个例子,上面我们已经得出先舍入第 3 位小数 最优,结果为 99.45,这时第2位得到进位后又能舍入了,结果为99.5,依次类推。。。。
那么我们的基本思路应该是先找到一个最小的能进位的位置(如果没有那么我们不舍入就是最优的),找到后将该位置舍入,然后继续找最小的能进位的位置,依次重复,直到t为0或者没有小数为止。
在这里我们还可以对上述操作进行优化 : 如果在第一次找到的能进位的位置为 i ,那么下次能进位的位置只可能为 i-1或没有,因为我们找到 位置 i 的 条件是前面没有能进位的位置。
特判, 只有整数,或者整数部分能多一位 ,例如 245,99.9.
int main() {
int n,t;
string s;
cin>>n>>t>>s;
int bef = -1;
for(int i=0;i<s.size();i++) {
if(s[i]=='.') {//区分出整数部分和小数部分
bef = i;
break;
}
}
if(bef == -1) cout<<s<<endl; //只有整数
else {
int flag = -1;
int limit = s.size();
for(int i=bef+1;i<s.size();i++) {//找到第一个最小的能进位的位置
if(flag != -1) break;
if(s[i]>='5') {
flag = i;
}
}
if(flag == -1) cout<<s<<endl; // 没有就输入原字符串
else {
if(flag == bef +1) { // 如果进位刚好是小数的第一位
int tof=1;
for(int i=bef-1;i>=0;i--) {
if(tof == 0) break;
if( s[i] == '9' && tof == 1) {
s[i] ='0';
tof = 1;
}
else if(tof==1){
s[i]++;
tof = 0;
}
}
if(tof == 1) {
cout<<'1';
}
for(int i=0;i<bef;i++) {
cout<<s[i];
}
cout<<endl;
}
else {
s[flag-1]++;
limit = flag;
t--;
int now = limit-1;
while(t--) {//一直向前进位直到不能进位或者 t=0
if(s[now]>='5') {
if(now == bef+1) {
int tof=1;
for(int i=bef-1;i>=0;i--) {
if(tof == 0) break;
if( s[i] == '9' && tof == 1) {
s[i] ='0';
tof = 1;
}
else if(tof == 1){
s[i]++;
tof = 0;
}
}
if(tof == 1) {
cout<<'1';
}
for(int i=0;i<bef;i++) {
cout<<s[i];
}
cout<<endl;
return 0;
}
else {
s[now-1]++;
limit = now;
now--;
}
}
else break;
}
for(int i=0;i<limit;i++) {
cout<<s[i];
}
cout<<endl;
}
}
}
return 0;
}