51nod1621 花钱买车牌

被这道题难了一下午,记录一下

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;
}

猜你喜欢

转载自blog.csdn.net/qq_41156122/article/details/81913308