• 【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;
    }
  • 相关阅读:
    身份证验证(c#和js)
    获取焦点问题
    关于加载设计器遇到一个或多个错误问题的解决方案
    关于如何使用自定义的结束消息循环的方式 (转载)
    多种重要源码下载
    关于线程同步(转载)
    ArrayList的使用技巧
    一些所谓有利于家庭生活的优点
    080801 30℃
    080731 31℃
  • 原文地址:https://www.cnblogs.com/wuhu-JJJ/p/11456404.html
Copyright © 2020-2023  润新知