【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。
题解:刚刚又调试了好久。。。但还是失败了。70(佛了我)
#include<bits/stdc++.h> #include<iostream> #include<algorithm> #include<queue> #include<cmath> #include<cstring> #include<cstdlib> #include<cstdio> using namespace std; const int oo=0x3f3f3f3f; const int N=10005; int cost,v,tt; int ans,sum,n,k,f[13],id,mx,e[13],jd; char s[N]; bool flag; int main(){ scanf("%d %d\n",&n,&k); scanf("%s",s+1); //cin>>s; for(int i=1;i<=n;i++) f[s[i]-'0']++; for(int i=0;i<=9;i++) mx=max(mx,f[i]); if(mx>=k){ printf("0\n"); for(int i=1;i<=n;i++) printf("%c",s[i]); return 0; } ans=oo; for(int i=0;i<=9;i++){ //for(int i=9;i>=0;i--){ sum=f[i]; cost=0; int j; //cout<<sum<<' '; for(j=1;;j++){ //cout<<sum; if(i-j>=0){ if(f[i-j]+sum<k) { sum+=f[i-j]; cost+=j*f[i-j]; } else { cost+=j*(k-sum); break; } } if(i+j<=9){ if(f[i+j]+sum<k) { sum+=f[i+j]; cost+=j*f[i+j]; } else { cost+=j*(k-sum); break; } } } if(cost<ans) { ans=cost; id=i; jd=j; tt=k-sum; } //tt_快接近满的时候还多下多少个需要改 //jd_表示要加或减的跨度多少 //cout<<i<<' '<<cost<<' '<<j<<endl; } printf("%d\n",ans); for(int i=1;i<=n;i++){ int d=s[i]-'0'; if(abs(d-id)<jd) s[i]=(char)(id+'0'); } //v表示已经改了多少个数字了 for(int i=1;i<=n;i++){ int d=s[i]-'0'; if(d-id==jd){ //将大的数字改小 if(v==tt) break; s[i]=(char)(id+'0'); v++; } } for(int i=n;i>=1;i--){ int d=s[i]-'0'; if(id-d==jd){ //将小的数字改大 if(v==tt) break; s[i]=(char)(id+'0'); v++; } } for(int i=1;i<=n;i++) printf("%c",s[i]); return 0; }