51nod 1621 花钱买车牌 优先队列

Posted 小小超plus

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1621 花钱买车牌 优先队列相关的知识,希望对你有一定的参考价值。

一个车牌号由n位数字组成。如果一个车牌至少有k位数字是相同的,那么我们就说这个车牌漂亮的车牌。现在华沙想要改变他自己的车牌,使得他的车牌变得漂亮。当然,改车牌是要花钱的。每改变一位数字所要花费的费用等于当前位上的新旧数字之差的绝对值。那么总费用就是每位上所花费用的总和。

举例如下,

旧牌为0123,新牌为7765,那么对应第一位所花费用为|0-7|=7,第二位为|1-7|=6,第三位为|2-6|=4,第四位为|3-5|=2,总和为7+6+4+2=19

 

华沙想用最少的钱,使他的车牌变得漂亮起来。现在给定n,k,和旧牌的号码,计算换牌的最少费,以及新牌的号码,

如果最少费用的号码有多个,我们取字典序最小的那个。

 

样例解释:

 

在样例中,把第二个数字换成“8”花费|9-8|=1,把第五个数字换成“8”也花了1。

把第六个数字换成“8”花费|6-8|=2.总费用为1+1+2=4,新号码为“888188”

 

两个长度为n的序列比较方法如下。

存在两个序列x,y,长度都是n。

如果存在i(1≤i≤n)和任意j(1≤j<i)使得 xiyi 并且 xjyj ,那么我们就说x比y小。



Input
单组测试数据
第一行,两个由空格隔开的数字n和k(2≤n≤10^4,2≤k≤n),表示旧牌的位数,和至少要有k位数字相同才能构成漂亮的车牌。
第二行有n位数字,代表华沙的旧车牌。(旧车牌中只有数字)。
Output
共两行,
第一行,一个整数,代表换牌的最小费用,
第二行,n位数字,表示新的车牌。
如果最小费用的车牌有多个,输出字典序最小的那个。
Input示例
6 5
898196
Output示例
4
888188


百度发现没人写过这个题的题解,本弱鸡就来一发题解。
用优先队列队列记录k位上是0-9的最优解,然后就是优先队列的规则(最坑的地方),代码写的很清楚。
最后就是在相同的最优解里找到数字最小的那个。
技术分享
  1 #include <iostream>
  2 using namespace std;
  3 #include<string.h>
  4 #include<set>
  5 #include<stdio.h>
  6 #include<math.h>
  7 #include<queue>
  8 #include<map>
  9 #include<algorithm>
 10 #include<cstdio>
 11 #include<cmath>
 12 #include<cstring>
 13 #include <cstdio>
 14 #include <cstdlib>
 15 #include<stack>
 16 #include<vector>
 17 struct lll
 18 {
 19     int weizhi;
 20     int zhi;
 21 }s;
 22 int biaozhun;
 23 struct cmp2{
 24     bool operator ()(lll &a,lll &b){
 25         //cout<<biaozhun<<"_"<<endl;
 26         //return fabs(a.zhi-biaozhun)>fabs(b.zhi-biaozhun);
 27         if(fabs(a.zhi-biaozhun)!=fabs(b.zhi-biaozhun))
 28             return fabs(a.zhi-biaozhun)>fabs(b.zhi-biaozhun);
 29         else
 30         {
 31             if(a.zhi==biaozhun)
 32                 return 1;
 33             else if(a.zhi>b.zhi)
 34                 return 0;
 35             else if(a.zhi<b.zhi)
 36                 return 1;
 37             else if(a.zhi>biaozhun)
 38             {
 39                 if(a.weizhi>b.weizhi)
 40                     return 1;
 41                 else
 42                     return 0;
 43             }
 44             else
 45             {
 46                 if(a.weizhi>b.weizhi)
 47                     return 0;
 48                 else
 49                     return 1;
 50             }
 51         }
 52     }
 53 };
 54 priority_queue<lll,vector<lll>,cmp2>TM[10];
 55 char a[11000];
 56 char goubi1[11000];
 57 char goubi2[11000];
 58 int b[15][11000];
 59 int n,m;
 60 int gougougou[20];
 61 int panduan(char s1[],char s2[])
 62 {
 63     for(int i=0;i<n;i++)
 64     {
 65         if(s1[i]>s2[i])
 66             return 0;
 67         else if(s2[i]>s1[i])
 68             return 1;
 69     }
 70     return 0;
 71 }
 72 int mp[20];
 73 int main()
 74 {
 75 
 76     cin>>n>>m;
 77     cin>>a;
 78     memset(gougougou,0,sizeof(gougougou));
 79     memset(mp,0,sizeof(mp));
 80     for(int i=0;i<n;i++)
 81     {
 82         goubi1[i]=a[i];
 83         goubi2[i]=a[i];
 84         mp[a[i]-0]=1;
 85     }
 86     for(int i=0;i<=9;i++)
 87     {
 88         biaozhun=i;
 89         for(int j=0;j<n;j++)
 90         {
 91             s.weizhi=j;
 92             s.zhi=a[j]-0;
 93             //cout<<s.zhi<<endl;
 94             TM[i].push(s);
 95         }
 96     }
 97     int min1=1e8;
 98     int sum;
 99     int t;
100     for(int i=9;i>=0;i--)
101     {
102         biaozhun=i;
103         for(int j=0;j<m;j++)
104         {
105             b[i][j]=TM[i].top().weizhi;
106             gougougou[i]+=fabs(TM[i].top().zhi-i);
107             TM[i].pop();
108         }
109         if(gougougou[i]<=min1)
110         {
111             min1=gougougou[i];
112             t=i;
113         }
114 
115     }
116     cout<<min1<<endl;
117     for(int i=0;i<m;i++)
118     {
119         //cout<<b[t][i]<<endl;
120         goubi1[b[t][i]]=t+0;
121     }
122     for(int i=t+1;i<=9;i++)
123     {
124         if(gougougou[i]==min1&&mp[i]==1)
125         {
126              for(int j=0;j<m;j++)
127             {
128             //cout<<b[t][i]<<endl;
129                 goubi2[b[i][j]]=i+0;
130             }
131             //cout<<goubi1<<"_"<<goubi2<<endl;
132             if(panduan(goubi1,goubi2)==0)
133             {
134                 for(int k=0;k<n;k++)
135                 {
136                     goubi1[k]=goubi2[k];
137                     goubi2[k]=a[k];
138                 }
139             }
140             else
141             {
142                 for(int k=0;k<n;k++)
143                 {
144                     goubi2[k]=a[k];
145                 }
146             }
147         }
148     }
149     cout<<goubi1<<endl;
150     return 0;
151 }
View Code

 








以上是关于51nod 1621 花钱买车牌 优先队列的主要内容,如果未能解决你的问题,请参考以下文章

51nod1428(优先队列)

51nod 1163 最高的奖励(贪心+优先队列)

51nod 1380 夹克老爷的逢三抽一 堆 脑洞题

51nod1061 最复杂的数 V2

51nod 1672 区间交(贪心)

51nod NOIP能力测评