題目
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;
}