Python30行解决
思路 ——
- for 0~9 循环找出应当相同的数字为
same_number:即对每一位进行abs()计算,排序代价选前K个并求和;记录最小值和此时对应的same_number。(详见代码及其中注释) - 因为要满足字典序最小输出,分析可得 —— 数字
nums[i]变为same_number时,满足临界代价的数字(即代价等于前K个代价的最大值的那几个数字)需要进行判断:若是由小变大,则应从后往前扫逐个变化;否则直接变化即可。
N, K = map(int, input().split())
nums = list(map(int, [i for i in input()])) # N长的手机号
cost = float('inf')
same_number, res = "#", [i for i in nums]
# --alg begiin-- #
for i in range(9): # 选出最优代价和即将相同的数字
gaps = [(j, abs(nums[j]-i)) for j in range(N)] # (原数字的index,该位修改后的代价)
gaps.sort(key=lambda x: x[1]) # 按代价排序
gaps = gaps[0:K] # 取最小的K个代价
sums = sum([j[1] for j in gaps]) # 代价总和
if sums < cost: # 优先数字小的 i->0~9
same_number = i
cost = sums
selection = [(j, abs(nums[j]-same_number)) for j in range(N)]
selection.sort(key=lambda x: x[1]) # 按代价排序
balance_value = selection[K-1][1] # 临界代价(对于临界代价的位要进行变大变小的判断)
selection = list(filter(lambda x:x[1]<=balance_value, selection)) # 筛选出可以更换的数字及序号
# 代价相同的情况下,若修改后变小,优先改高位,否则改低位
cnt = 0 # 已修改的位数
for i, c in selection:
if c == balance_value and nums[i] < same_number: # 即将变大,先标记,暂不更改
res[i] = "b"
else:
res[i] = same_number if cnt<K else nums[i]
cnt += 1
for i in range(N-1, -1, -1): # 后从往前选由小变大的,直到完成
if res[i] == "b":
res[i] = same_number if cnt<K else nums[i]
cnt +=1
print('%d\n%s' % (cost, ''.join(map(str, res)))) 
京公网安备 11010502036488号