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)使得 xi<yi 并且 xj=yj ,那么我们就说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 }
以上是关于51nod 1621 花钱买车牌 优先队列的主要内容,如果未能解决你的问题,请参考以下文章