【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,&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
");
        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
",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;
}
原文地址:https://www.cnblogs.com/wuhu-JJJ/p/11456404.html