Tema
Se pueden usar denominaciones de monedas de 10, 20, 50, 100 yuanes para formar las denominaciones dadas en la pregunta, y se requiere la cantidad mínima de monedas
análisis
Al principio, los compañeros de equipo querían usar un montón de if-else para resolver el problema, y luego WA hizo innumerables publicaciones ...
Pensé en una forma relativamente simple de resolver este problema, y la longitud de esta tabla es solo13 int
Antes de comenzar el análisis, no consideremos la solución que aparece -1. Es decir, hay una situación en la que mod 10 no es igual a 0, porque este juicio es muy simple
ley
Determine una ley obvia antes de comenzar a empujar esta tabla
Si hay dos esquemas que requieren el mismo número de monedas y se pueden componer las denominaciones del primer esquema, el segundo esquema no es deseable.
Prueba: si uso el primer conjunto de planes, entonces debo poder usar el segundo plan. Incluso si el segundo plan no puede formar más denominaciones, esta elección es completamente correcta.
inferencia
Según la ley, se pueden obtener las siguientes inferencias
1. No existe un plan que contenga dos de 10 yuanes y, de manera similar, dos de 50 yuanes no existen
Prueba: si hay un plan que contiene dos de 10 yuanes, podemos optar por reemplazar este plan con uno de 10 yuanes y uno de 20 yuanes. Podemos estar seguros de que dos de 10 yuanes solo pueden formar las dos denominaciones de 10 y 20. Y 10 yuanes y 20 yuanes pueden formar tres denominaciones de 10 yuanes, 20 yuanes y 30 yuanes. Según la ley, se determina que este esquema no es factible. Del mismo modo, dos 50 yuanes pueden ser reemplazados por 50 + 100
2. Solo se utilizan 4 monedas distintas de 100 yuanes, y solo hay dos esquemas de composición: 10, 20, 20, 50 y 20, 20, 20, 50
Prueba: para 4 monedas, los esquemas 10, 20, 20 y 50 pueden formar todas las cajas de 10-100, por lo que si cualquier otro esquema es razonable, debe poder formar una caja de más de 100 yuanes. Según el Corolario 1, 50 yuanes no se pueden repetir, por lo que el valor más grande que se puede formar es usar 20, 20, 20 y 50 para formar 110.
3. No se utilizan 5 monedas distintas de 100 yuanes
Prueba: Primero, si se usan 5 monedas, según el Corolario 1, solo hay dos combinaciones que se pueden obtener: 10, 20, 20, 20, 50 o 120 yuanes, y 20, 20, 20, 20, 50 o 130 yuanes. Entonces, no importa cuál sea la combinación, la conclusión del Corolario 2 no es tan buena como la combinación de 10, 20, 20, 50, 100, porque esta combinación puede completar todas las soluciones dentro de 10-200. Entonces, de acuerdo con la ley, las dos combinaciones anteriores son combinaciones incorrectas.
4. Las denominaciones superiores a 110 yuanes deben estar compuestas por una o varias monedas de 100 yuanes.
Prueba: Esto es muy simple y puede derivarse directamente del razonamiento 3. Por lo tanto, para denominaciones superiores a 110 yuanes, continúe a -100 hasta que se cumplan las condiciones anteriores.
Por metro
Entonces sabemos que solo hay 4 monedas que no son 100 yuanes como máximo, entonces podemos obtener todas las combinaciones (omitir 0)
1
2
5
1 2
1 5
2 2
2 5
1 2 2
1 2 5
2 2 2
2 2 5
1 2 2 5
2 2 2 5
Luego, podemos escribir los números que pueden formar estas situaciones.
1
2
5
1 2 3
1 5 6
2 4
2 5 7
1 2 3 4 5
1 2 3 5 6 7 8
2 4 6
2 4 5 7 9
1 2 3 4 5 6 7 8 9 10
2 4 6 7 9 11
Con la ayuda de operaciones de bits, podemos hacer esto:
print(1 << 1)
print(1 << 2)
print(1 << 5)
print((1 << 1) + (1 << 2) + (1 << 3))
print((1 << 1) + (1 << 5) + (1 << 6))
print((1 << 2) + (1 << 4))
print((1 << 2) + (1 << 5) + (1 << 7))
print((1 << 1) + (1 << 2) + (1 << 3) + (1 << 4) + (1 << 5))
print((1 << 1) + (1 << 2) + (1 << 3) + (1 << 5) + (1 << 6) + (1 << 7) + (1 << 8))
print((1 << 2) + (1 << 4) + (1 << 6))
print((1 << 2) + (1 << 4) + (1 << 5) + (1 << 7) + (1 << 9))
print((1 << 1) + (1 << 2) + (1 << 3) + (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7) + (1 << 8) + (1 << 9) + (1 << 10))
print((1 << 2) + (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7) + (1 << 9) + (1 << 11))
Puede intentar comprender el principio de esta tabla,Es decir, cada bocado se utiliza como elemento de la mesa.
Se puede ver que el valor máximo es de solo 110 yuanes. Y observe que la moneda con la denominación más grande es 100. Y 110 yuanes pueden estar compuestos por no 100 yuanes o 10 yuanes + 100 yuanes De manera similar, hay dos combinaciones de 100 yuanes. Por lo tanto, deben tenerse en cuenta cuatro situaciones: 1.
100 yuanes se componen de 100 yuanes, 110 yuanes se componen de
100 yuanes 2, 100 yuanes se componen de
100 yuanes, 110 yuanes se componen de no 100 yuanes, 3, 100 yuanes se componen de no 100 yuanes, 110 yuanes Use 100 yuanes por 4,
100 yuanes por no 100 yuanes, 110 yuanes por no 100 yuanes
Entonces piénselo todo, lo que sea más pequeño
Código AC
#include<bits/stdc++.h>
using namespace std;
vector<int> res;
void init() {
res.push_back(0);
res.push_back(2);
res.push_back(4);
res.push_back(32);
res.push_back(14);
res.push_back(98);
res.push_back(20);
res.push_back(164);
res.push_back(62);
res.push_back(494);
res.push_back(84);
res.push_back(692);
res.push_back(2046);
res.push_back(2804);
}
int get_ans(int as) {
int t = -1;
for (int i = 0; i < res.size(); ++i) {
if ((res[i] ^ as) + (res[i] & as) == res[i]) {
t = i;
break;
}
}
switch (t) {
case 0:
return 0;
case 1:
case 2:
case 3:
return 1;
case 4:
case 5:
case 6:
case 7:
return 2;
case 8:
case 9:
case 10:
case 11:
return 3;
case 12:
case 13:
return 4;
}
return 1000;
}
int main() {
#ifdef ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
auto start_clock_for_debug = clock();
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cin.tie(0);
int t;
cin >> t;
init();
while (t--) {
int n;
cin >> n;
int hun[4];
int cnt[4][15];
memset(cnt, 0, sizeof(cnt));
memset(hun, 0, sizeof(hun));
bool flag = false;
for (int i = 0; i < n; ++i) {
int tmp;
cin >> tmp;
if (flag) continue;
if (tmp % 10) {
flag = true;
continue;
}
// 100 + 110
int tmp0 = tmp;
if (tmp0 % 100 > 10 and tmp0 > 100) {
hun[0] = max(tmp0 / 100, hun[0]);
tmp0 %= 100;
cnt[0][tmp0 / 10]++;
} else if (tmp0 > 100) {
hun[0] = max((tmp0 - 100) / 100, hun[0]);
tmp0 %= 100;
cnt[0][tmp0 / 10 + 10]++;
} else {
cnt[0][tmp0 / 10]++;
}
// 100
int tmp1 = tmp;
if (tmp1 % 100 == 0 and tmp1 > 100) {
hun[1] = max((tmp1 - 100) / 100, hun[1]);
cnt[1][10]++;
} else {
hun[1] = max(tmp1 / 100, hun[1]);
cnt[1][(tmp1 % 100) / 10]++;
}
// 110
int tmp2 = tmp;
if (tmp2 % 100 == 10 and tmp2 > 100) {
hun[2] = max((tmp2 - 100) / 100, hun[2]);
cnt[2][11]++;
} else {
hun[2] = max(tmp2 / 100, hun[2]);
cnt[2][(tmp2 % 100) / 10]++;
}
// None
int tmp3 = tmp;
hun[3] = max(tmp3 / 100, hun[3]);
cnt[3][(tmp3 % 100) / 10]++;
}
if (flag) {
cout << -1 << endl;
continue;
}
int ans;
int get_ans[4];
for (int j = 0; j < 4; ++j) {
ans = 0;
for (int k = 1; k < 13; ++k) {
if (cnt[j][k]) {
ans += 1 << k;
}
}
get_ans[j] = get_ans(ans) + hun[j];
}
sort(get_ans, get_ans + 4);
cout << get_ans[0] << endl;
}
#ifdef ACM_LOCAL
auto end_clock_for_debug = clock();
cerr << "Run Time: " << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
#endif
return 0;
}