UOJ #553. 第一饭堂
【题目描述】:
已知第一饭堂饭菜的价格有N位(坑爹吧!),如果一个价格有不小于K个数位完全相同,那么这个数字就被认为是漂亮的,否则这个数字被认为是不漂亮的。饭堂班长想改变其中一个饭菜的价格,改变价格中的一位需要花费一些钱,所需费用是这一位改变量之差的绝对值。
饭堂班长希望你能把这个价格变漂亮,求出最小费用,同时给出字典序最小的一个方案。
【输入描述】:
第1行:两个用空格隔开的数字N和K(2≤n≤10^4, 2≤k≤n)。
第2行:一个N位的数字表示原来的价格。
【输出描述】:
第1行:最小费用。
第2行:所求方案。
【样例输入1】:
6 5
898196
【样例输出1】:
4
888188
【样例输入2】:
3 2
533
【样例输出2】:
0
533
【样例输入3】:
10 6
0001112223
【样例输出3】:
3
0000002223
【时间限制、数据范围及描述】:
时间:1s 空间:256M 10%的数据:N≤5;
20%的数据:N≤10;
30%的数据:N≤18;
70%的数据:N≤500;
对于100%的数据,2≤N≤10000,2≤k≤n。
思路:
记录s(原价)中0~9的个数,然后从0开始贪心(贪最小字典序),每算出一种答案比较一次,以防出现非最优解的情况
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; string fin,s,tmp; int n,k,i,j,t,ans1,ans,a[10]; void change(string &s,int x,int y) { int i; if (x>y) for(int i=0; i<n; i++) if(s[i]==x+'0') { t--; s[i]=y+'0'; ans1+=abs(y-x); if(!t) break; } if(x<y) for(int i=n-1; i>=0; i--) if(s[i]==x+'0') { t--; s[i]=y+'0'; ans1+=abs(y-x); if(!t) break; } } int main() { scanf("%d%d",&n,&k); cin>>s; for(int i=0; i<n; i++) a[s[i]-'0']++; ans=int(1e9); fin=s; for(int i=0; i<10; i++) { t=k-a[i],ans1=0; tmp=s; if (t>0) for(int j=1; j<=9; j++) { if(i+j<10) change(tmp,i+j,i); if(!t) break; if(i-j>=0) change(tmp,i-j,i); if(!t) break; } if(ans1<ans) { ans=ans1; fin=tmp; } else if(ans1==ans&&tmp<fin) fin=tmp; /*printf("%d\n",ans); cout<<fin<<endl;*/ } printf("%d\n",ans); cout<<fin<<endl; return 0; }