被这道题难了一下午,记录一下
1,枚举,枚举变成k个0,1,……9的代价,其中代价和最小的就是答案
2,然后,再枚举,从代价小的开始枚举,例如,花费1的代价看能有几个
变成了,不够的话,就枚举花费2的代价,直到有k个,这样就满足了题意
3,为了保证字典序最小,还要注意一点,同样花费2的代价,5变到3要比1变到2要好,
所以要优先减操作,减操作正序进行,加操作倒序进行(同样是为了保证字典序最小)
详见代码:
#include<stdio.h>
#include<string>
#include<iostream>
using namespace std;
const int N = 1e4+9;
const int inf = 0x3f3f3f3f;
int n,k,min_sum,num[10];
string ans,tmp,in;
int main()
{
ios::sync_with_stdio(false);
min_sum=inf;
cin>>n>>k;
cin>>in;
for(int i = 0; i<n; i++)
num[in[i]-'0']++;
for(int i = 0; i<10; i++)//枚举0~9的代价
{
int need = k-num[i],sum=0;
tmp=in;
for(int j = 1; j<10&&need>0;j++) //从小到大枚举代价
{
if(i+j<=9) //一点小剪枝 ,去掉也行
{
for(int v = 0;v<n&&need>0;v++ )
if(tmp[v]-'0'-j==i)
{
tmp[v]=i+'0';
sum +=j;
need--;
}
}
if(i-j>=0)//一点小剪枝,去掉也行
{
for(int v = n-1;v>=0&&need>0;v--)
if(tmp[v]-'0'+j==i)
{
tmp[v]=i+'0';
sum+=j;
need--;
}
}
}
if(sum<min_sum&&need<=0)
{
ans=tmp;
min_sum=sum;
}
else if(sum==min_sum&&tmp<ans)
ans=tmp;
}
cout<<min_sum<<endl<<ans<<endl;
return 0;
}