【2021年度训练联盟热身训练赛第五场】
H In-place Sorting (贪心 字典序比较)
【题目描述】
Woe is you – for your algorithms class you have to write a sorting algorithm, but you missed the relevant lecture! The subject was in-place sorting algorithms, which you deduce must be algorithms that leave each input number in its place and yet somehow also sort the sequence.
Of course you cannot change any of the numbers either, then the result would just be a difffferent sequence. But then it hits you: if you flflip a 6 upside-down, it becomes a 9, and vice versa! Certainly no one can complain about this since you changed none of the digits! The deadline to hand in the exercise is in fifive hours. Try to implement this sorting algorithm before then!
【输入描述】
The input consists of:
• A line with an integer n (2 ≤ n ≤ 10 000), the number of integers in the input sequence.
• n lines, the ith of which contains a positive integer xi (1 ≤ xi ≤ 1018), the ith number of the sequence.
【输出描述】
If the sequence cannot be sorted non-decreasingly by flipping some number 6 or 9 in input 1, output “not possible”. Otherwise, output “possible” followed by the sorted sequence - each number on its own line.
If there is more than one valid solution, please output the smallest sequence.
【示例1】
输入
4
9
7
7
9
输出
possible
6
7
7
9
【示例2】
输入
4
97
96
66
160
输出
possible
67
69
69
160
【示例3】
输入
3
80
97
79
输出
impossible
【示例4】
输入
2
197
166
输出
possible
167
169
【解题思路】
本题输入一组数字,我们可以每个数字当中的6和9互相替换。问能否进行一些替换以后,使得所有数字递增(可以相等)。
显然我们可以采取贪心的策略。
这里我们用字符串类型来存取数字,方便进行替换操作以及字典序比较。
首先将第一个数字当中的所有9都替换成6,使其最小。
然后从第二个数字开始往后处理:
如果当前数字长度比前一个数字短,那么显然不可能满足递增,直接输出impossible并结束。
如果当前数字长度比前一个数字长,那么显然已经满足递增,我们将数字当中的所有9都替换成6,使其最小,然后进入处理下一个数字。
如果当前数字长度和前一个数字一样长,那么我们要使其大于前一个数字但又尽可能地小。
首先判断是否有可能满足递增。我们把数字当中所有的6都替换成9,如果替换以后的数字还比前一个数字小,那么显然不可能满足递增,输出impossible并结束。
如果替换以后的数字满足比前一个数字大,但它还不一定是最小的,我们逐位检查能否把数字中的9替换成6,使其尽可能得小,这就是贪心的最优策略。
【AC代码】
#include
#include
#include
using namespace std;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;
string s[10005];
cin>>n;
for(int i=0;i<n;i++)
cin>>s[i];
int len=s[0].length();
for(int j=0;j<len;j++)
if(s[0][j]=='9')
s[0][j]='6';//将第一个数的所有9换成6
int flag=1;
for(int i=1;i<n;i++)
{
len=s[i].length();
if(len<s[i-1].length())
{
flag=0;
break;
}//如果长度比前一个数小,则不可能
if(len>s[i-1].length())
{
for(int j=0;j<len;j++)
if(s[i][j]=='9')
s[i][j]='6';
continue;
}//如果长度比前一个数大,则将所有9换成6即可
for(int j=0;j<len;j++)
if(s[i][j]=='6')
s[i][j]='9';
if(s[i-1].compare(s[i])>0)
{
flag=0;
break;
}//如果将所有6换成9还比前一个数小,则不可能
for(int j=0;j<len;j++)
{
if(s[i][j]=='9')
{
s[i][j]='6';
if(s[i-1].compare(s[i])>0)
s[i][j]='9';
}
}//从前往后试把9换成6
/*
for(int j=len-1;j>=0;j--)
{
if(s[i][j]=='9')
{
s[i][j]='6';
if(s[i-1].compare(s[i])>0)
s[i][j]='9';
}
}//从后往前试把9换成6
*///这个循环不要也行,因为完整遍历过一遍就已经能够保证是当前的最优解了
}
if(flag==0)
cout<<"impossible"<<endl;
if(flag==1)
{
cout<<"possible"<<endl;
for(int i=0;i<n;i++)
cout<<s[i]<<endl;
}
return 0;
}