題目描述:
鏈接:https://www.nowcoder.com/questionTerminal/005af31a10834b3688911463065ab47d
來源:牛客網
A 國的手機號碼由且僅由 N 位十進制數字(0-9)組成。一個手機號碼中有至少 K 位數字相同則被定義為靚號。A 國的手機號可以有前導零,比如 000123456 是一個合法的手機號。 小多想花錢將自己的手機號碼修改為一個靚號。修改號碼中的一個數字需要花費的金額為新數字與舊數字之間的差值。比如將 1 修改為 6 或 6 修改為 1 都需要花 5 塊錢。 給出小多現在的手機號碼,問將其修改成一個靚號,最少需要多少錢?
輸入描述:
第一行包含2個整數 N、K,分別表示手機號碼數字個數以及靚號至少有 K 個數字相同。
第二行包含 N 個字符,每個字符都是一個數字('0'-'9'),數字之間沒有任何其他空白符。表示小多的手機號碼。
數據范圍:
2 <= K <= N <= 10000
輸出描述:
第一行包含一個整數,表示修改成一個靚號,最少需要的金額。
第二行包含 N 個數字字符,表示最少花費修改的新手機號。若有多個靚號花費都最少,則輸出字典序最小的靚號。
思路分析:
是一道貪心求解的題。由於一共就10個數字,求每一位數字作為靚號的花費。例如對於787585這個號,n=6,k=5。首先判斷設置5個9的情況,再針對設置每個數字到9的花費進行排序。這里利用了一個結構體,包含了當前數的在號碼的位置,其初始值,其目標值,以及從初始值轉換到目標值所需要的花費。將花費從小到大進行排序,對於花費一致的數,這里需要輸出字典序最小的結果,因此當當前數比目標數小,優先處理后面的數。
代碼:
1 #include<stdio.h> 2 #include<iostream> 3 #include<vector> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<limits.h> 7 using namespace std; 8 9 struct node{ 10 int cosume; 11 int idx; 12 int target; 13 int ori; 14 }; 15 16 int cmp(node a, node b) 17 { 18 if(a.cosume!=b.cosume) 19 return a.cosume < b.cosume; 20 if(a.idx < b.idx) 21 return a.target < a.ori; 22 return b.target > b.ori; 23 } 24 25 void process(int num[], int n, int k) 26 { 27 int cnt = INT_MAX, tmp; 28 int i,j; 29 node nx[n]; 30 int res[n]; 31 for(i=9; i>=0; i--) 32 { 33 for(j=0; j<n; j++) 34 { 35 nx[j].cosume = abs(i-num[j]); 36 nx[j].idx = j; 37 nx[j].target = i; 38 nx[j].ori = num[j]; 39 } 40 sort(nx, nx+n, cmp); 41 tmp = 0; 42 for(j=0; j<k; j++) 43 tmp += nx[j].cosume; 44 if(tmp <= cnt) 45 { 46 cnt = tmp; 47 for(j=0; j<n; j++) 48 res[j] = num[j]; 49 for(j=0; j<k; j++) 50 res[nx[j].idx] = i; 51 } 52 } 53 printf("%d\n", cnt); 54 for(i=0; i<n; i++) 55 printf("%d", res[i]); 56 printf("\n"); 57 } 58 59 int main() 60 { 61 int n,k; 62 scanf("%d%d", &n, &k); 63 char number[n]; 64 scanf("%s", number); 65 int num[n]; 66 for(int i=0; i<n; i++) 67 num[i] = number[i]-'0'; 68 process(num, n, k); 69 return 0; 70 }