题目
题目大意
给你一个整数 n n (,不含前导零),你能够将任意两个相邻位置上的数互换位置,每交换一次算一步,每一次交换过后的数不能有前导零。现在要求以最少的步数使这个数变为 25 25 的倍数,输出这个步数。
分析
比赛的时候疯狂地分类讨论,仿佛灵魂都被净化了,结果还是没做出来……
25 25 的倍数的特征是末两位是 00 00 , 25 25 , 50 50 或 75 75 ,所以从数 n n 中揪出, 2 2 ,, 7 7 ,看把它们弄到最后一位(或倒数第2位)需要多少步。
具体来说,以为例,贪心地想:如果有多个
2
2
(),那肯定要选靠后的,所以从后往前找(某STL大神告诉蒟蒻string
类有个函数叫rfind()
是从后往前找……)。先找到
5
5
的位置记为,然后删掉这个
5
5
(主要是为了避免在
2
2
前面要多花一步的情况),再找到的位置记为
pos1
p
o
s
1
(如果
5
5
在前面,删掉
5
5
后的和不删
5
5
),那么答案就是,就是把它们两个放回原位。
还有一点,注意前导零,具体看代码。
代码
把上诉操作封装成函数,调用4次即可。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
int len;
string A;
int Try(char i,char j){
string tmp=A;
int pos2=tmp.rfind(j);//rfind大法好
if(pos2==-1)
return INF;
tmp.erase(pos2,1);//erase要写两个参数(折磨一个从来不用string的人= =)
int pos1=tmp.rfind(i);
if(pos1==-1)
return INF;
//此时已经删掉字符j,如果有前导零,说明j不能直接与后面的交换
//如50323,删掉5后变为0323,需要先将除开前导零后第一个字符(3)一道最前面,计算代价
//变为53023后即可正常操作
int cnt=0;
while(tmp[cnt]=='0')
cnt++;
return cnt+len-2-pos1+len-1-pos2;
}
int main(){
cin>>A;
len=A.length();
int Ans=INF;
Ans=min(Ans,Try('0','0'));
Ans=min(Ans,Try('2','5'));
Ans=min(Ans,Try('5','0'));
Ans=min(Ans,Try('7','5'));
if(Ans==INF) printf("-1");
else printf("%d",Ans);
}