题目
http://acm.ecnu.edu.cn/problem/3290/
题意:“非上升数”表示一个整数的高位数码不会小于低位数码。如54332111, 111等。给定一个整数n,找出不小于n的最小“非上升数”。
解题思路
最自然的想法是,通过扫描s[i] < s[i+1]找到上升点,然后对上升点前的s[i-1]+1,后面全部填0。但是要考虑到s[i-1]+1后可能会破坏前面的非上升序列,因此还要将前面的元素考虑进来。
采取的办法是,在扫描上升点的同时,维护经过的最小数字及位置,找到上升点后,判断s[i-1]+1和该最小数字的大小,如果s[i-1]+1更小,那就在后面填0即可,否则要对最小数字+1,并在其后全填0。(实质是让填0前的那个数字保持最小)
例子:7400920的上升点在第二个0和9之间,如果变成7101000不满足“非上升”,但是变成7410000则满足。
AC代码
#include <iostream>
using namespace std;
int main()
{
int kase;
cin >> kase;
string s;
for(int t = 0; t < kase; ++t)
{
cin >> s;
int min_num = 10, min_pos = 0; //最小数字及所在小标
for (int i = 0; i < s.size()-1; ++i)
{
if (s[i] < s[i+1]) //出现上升
{
int tmp = s[i] - '0' + 1, pos = (tmp>min_num)?min_pos:i; //pos为更新的位置
//要更新的数字加1,后面全填0
s[pos]++;
for(int j = pos + 1; j < s.size(); ++j)
s[j] = '0';
break;
}
else if (s[i]-'0' < min_num) //维护经过的最小数字
{
min_num = s[i] - '0';
min_pos = i;
}
}
cout << "case #" << t << ':' << endl;
cout << s << endl;
}
return 0;
}