1004 To Buy or Not to Buy - Hard Version
Statement
Metadata
- 作者: CHEN, Yue
- 单位: 浙江大学
- 代码长度限制: 16 KB
- 时间限制: 400 ms
- 内存限制: 64 MB
Eva would like to make a string of beads with her favorite colors so she went to a small shop to buy some beads. There were many colorful strings of beads. However the owner of the shop would only sell the strings in whole pieces. Hence in some cases Eva might have to buy several strings to get all the beads she needs. With a hundred strings in the shop, Eva needs your help to tell her whether or not she can get all the beads she needs with the least number of extra beads she has to pay for.
For the sake of simplicity, let's use the characters in the ranges [0-9], [a-z], and [A-Z] to represent the colors. In sample 1, buying the 2nd and the last two strings is the best way since there are only 3 extra beads. In sample 2, buying all the three strings won't help since there are three R
beads missing.
Input Specification
Each input file contains one test case. Each case first gives in a line the string that Eva wants. Then a positive integer
Output Specification
For each test case, print your answer in one line. If the answer is Yes
, then also output the least number of extra beads Eva has to buy; or if the answer is No
, then also output the number of beads missing from all the strings. There must be exactly 1 space between the answer and the number.
Sample Input 1
Sample Output 1
Sample Input 2
Sample Output 2
Solution
#include <bits/stdc++.h>
using namespace std;
#define dbg(x...) \
do { \
cout << "\033[32;1m" << #x << " -> "; \
err(x); \
} while (0)
void err() {
cout << "\033[39;0m" << endl;
}
template <class T, class... Ts>
void err(const T& arg, const Ts&... args) {
cout << arg << ' ';
err(args...);
}
const int N = 1e3 + 10;
int n, cnt[110][220], S[110][220], tot[220], need[220], has[220];
char s[N], t[110][N];
int id[220], cntID, res, loop;
void dfs(int cur, int fee, int gap) {
if (fee >= res)
return;
if (gap == 0) {
res = fee;
return;
}
if (cur > n)
return;
++loop;
if (loop > 500)
return;
for (int i = 1; i <= cntID; ++i) {
if (S[cur][i] < need[i] - has[i])
return;
}
int preGap = gap;
int preFee = fee;
for (int i = 1; i <= cntID; ++i) {
if (cnt[cur][i]) {
fee -= max(0, has[i] - need[i]);
gap -= max(0, need[i] - has[i]);
has[i] += cnt[cur][i];
fee += max(0, has[i] - need[i]);
gap += max(0, need[i] - has[i]);
}
}
if (gap < preGap)
dfs(cur + 1, fee, gap);
for (int i = 1; i <= cntID; ++i) {
if (cnt[cur][i]) {
has[i] -= cnt[cur][i];
}
}
dfs(cur + 1, preFee, preGap);
}
int main() {
cntID = 0;
for (int i = '0'; i <= '9'; ++i) id[i] = ++cntID;
for (int i = 'a'; i <= 'z'; ++i) id[i] = ++cntID;
for (int i = 'A'; i <= 'Z'; ++i) id[i] = ++cntID;
scanf("%s", s + 1);
scanf("%d", &n);
for (int i = 1; s[i]; ++i) ++need[id[s[i]]];
for (int i = 1; i <= n; ++i) {
scanf("%s", t[i] + 1);
for (int j = 1; t[i][j]; ++j) {
++cnt[i][id[t[i][j]]];
++tot[id[t[i][j]]];
}
}
for (int i = n; i >= 1; --i) {
for (int j = 1; j <= cntID; ++j) S[i][j] = S[i + 1][j] + cnt[i][j];
}
int gap = 0;
for (int i = 1; i <= cntID; ++i) {
gap += max(0, need[i] - tot[i]);
}
if (gap > 0) {
printf("No %d\n", gap);
return 0;
}
res = 1e9;
int Slen = strlen(s + 1);
dfs(1, 0, Slen);
printf("Yes %d\n", res);
return 0;
}