题目描述
A国的手机号码由且仅由N位十进制数字(0-9)组成。一个手机号码中有至少K位数字相同则被定义为靓号。
A国的手机号可以有前导零,比如000123456是一个合法的手机号。
小多想花钱将自己的手机号码修改为一个靓号。修改号码中的一个数字需要花费的金额为新数字与旧数字之间的差值。
比如将1修改为6或6修改为1都需要花5块钱。
给出小多现在的手机号码,问将其修改成一个靓号,最少需要多少钱?
- 输入描述
第一行包含2个整数N、K,分别表示手机号码数字个数以及靓号至少有K个数字相同。
第二行包含N个字符,每个字符都是一个数字('0'-'9'),数字之间没有任何其他空白符。表示小多的手机号码。
数据范围:2 <= K <= N <= 10000
- 输出描述
第一行包含一个整数,表示修改成一个靓号,最少需要的金额。
第二行包含N个数字字符,表示最少花费修改的新手机号。若有多个靓号花费都最少,则输出字典序最小的靓号。
- 示例
输入:
6 5
787585
输出:
4
777577
找规律
最少花费通过设置上下界依次对求每个数字修改的差值的和进行求得。进行值修改的时候要注意,大于的要从前往后,小于的要从后往前,这样输出的总是字典序最小的。
def select_phone_number(seq, k):
front, rear = min(seq), max(seq)
value, compare = 0, float('inf')
for cur in range(front, rear+1):
subtraction = [abs(cur-su) for su in seq]
traction = sorted(subtraction)
current = sum(traction[:k])
if current < compare:
compare = current
value = cur
pos = [value-su for su in seq]
stand = sorted(list(set(map(lambda x: abs(x), pos))))
while k > 0:
nxt = min(stand)
if nxt == 0:
k -= pos.count(0)
stand.remove(nxt)
continue
left = value + nxt
while k > 0 and left in seq:
li = seq.index(left)
seq[li] = value
k -= 1
right = value - nxt
while k > 0 and right in seq:
ri = len(seq)-1-(seq[::-1].index(right))
seq[ri] = value
k -= 1
stand.remove(nxt)
return compare, seq
if __name__ == '__main__':
[n, k] = list(map(int, input().strip().split()))
seq = list(map(int, list(input().strip())))
value, res = select_phone_number(seq, k)
print(value)
print(''.join(map(lambda ru: str(ru), res)))
(最近更新:2019年09月01日)