1. 程式人生 > >51Nod-1621-花錢買車牌

51Nod-1621-花錢買車牌

ACM模版

描述

描述

題解

水題不水,有坑。

思路炒雞簡單,首先我們記錄下來 09 每個數字的個數,然後列舉讓 x 出現 k 次的最小花費。

這裡先說第一個容易錯的點兒,那就是當初始狀態就滿族時,直接特判最小花費為 0,按照原數輸出;
第二個容易錯的地方便是,數字的變更的貪心策略,假如說最優解釋讓 x 出現 k 次,那麼我們需要先考慮將 xix+i 變成 x,然後是 xi1x+i+1 變成 x,如果說將 xix+i 都變成 x 都不夠 k 個,那麼我們繼續往兩邊查詢,然而如果用不了這麼多呢?我們究竟有限變 xi 呢還是 x+i,這裡,我們採用正序一遍將 x

+i 變成 x,然後逆序一遍將 xi 變成 x,直到夠為止,這樣能保證一些情況字典序最小;
第三個容易錯的地方便是,當最小花費相同時,並不是 x 越小字典序就越小,比如說,n=8,k=4,num=22294777,那麼最小花費是 2,對應的方案有兩種,2229277722274777,前者 x=2 後者是 x=7,但是很明顯後者字典序更小,所以我們需要將兩個串兒進行比較,不能單純的保留最小 x

大致就是這些,沒毛病,沒有其他的可能會錯的地方了。

程式碼

#include <iostream>

using namespace std;

const int MAXN = 1e4
+ 10; const int MAX_DIG = 10; const int INF = 0x3f3f3f3f; int n, k; int cnt[MAX_DIG]; int num[MAXN]; int A[MAXN], B[MAXN]; void get_AB(int tmp[], int tot) { memcpy(tmp, num, sizeof(num)); int K = k - cnt[tot]; for (int i = 1; i < MAX_DIG && K; i++) { int l = tot - i, r = tot + i; for
(int j = 0; j < n && K; j++) { if (tmp[j] == r) { tmp[j] = tot; K--; } } for (int j = n - 1; j >= 0 && K; j--) { if (tmp[j] == l) { tmp[j] = tot; K--; } } } } bool cmp_AB() { for (int i = 0; i < n; i++) { if (A[i] > B[i]) { return 1; } else if (A[i] < B[i]) { return 0; } } return 0; } int main(int argc, const char * argv[]) { cin >> n >> k; for (int i = 0; i < n; i++) { scanf("%1d", num + i); cnt[num[i]]++; } for (int i = 0; i < MAX_DIG; i++) { if (cnt[i] >= k) { printf("0\n"); for (int j = 0; j < n; j++) { printf("%d", num[j]); } putchar(10); return 0; } } int min_cost = INF; for (int i = 0; i < MAX_DIG; i++) { int tmp = 0, K = k - cnt[i]; for (int j = 1; j < MAX_DIG; j++) { int l = i - j, r = i + j; if (l >= 0) { if (K > cnt[l]) { tmp += j * cnt[l]; K -= cnt[l]; } else { tmp += j * K; K = 0; } } if (!K) { break; } if (r < MAX_DIG) { if (K > cnt[r]) { tmp += j * cnt[r]; K -= cnt[r]; } else { tmp += j * K; K = 0; } } if (!K) { break; } } if (tmp < min_cost) { min_cost = tmp; get_AB(A, i); } else if (tmp == min_cost) { get_AB(B, i); if (cmp_AB()) { swap(A, B); } } } printf("%d\n", min_cost); for (int i = 0; i < n; i++) { printf("%d", A[i]); } putchar(10); return 0; }