Grouping
Explicación
Definimos como el puntaje máximo posible para el subconjunto de conejos representado por la máscara .
La transición involucra dos pasos para cada máscara :
- Puntaje base: Inicializamos calculando la suma de para todos los pares dentro de la máscara. Esto asume que todos los conejos de la máscara forman un solo grupo.
- Fusión de subconjuntos: Mejoramos partiendo la máscara en dos submáscaras disjuntas e . La transición es:
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector a(n, vector<int>(n));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) { cin >> a[i][j]; }
}
vector<ll> dp(1 << n);
// Recorremos todos los subconjuntos posibles de conejos
for (int i = 1; i < (1 << n); i++) {
// Calculamos el puntaje interno si este subconjunto forma UN solo grupo
for (int j = 0; j < n; j++) {
if (!(i >> j & 1)) continue;
for (int k = j + 1; k < n; k++) {
if (!(i >> k & 1)) continue;
dp[i] += a[j][k];
}
}
// Recorremos todas las submáscaras j de la máscara actual i
// Intentamos partir la máscara en grupos más pequeños para hallar un mejor puntaje
for (int j = (i - 1) & i; j > 0; j = (j - 1) & i) {
dp[i] = max(dp[i], dp[j] + dp[i ^ j]);
}
}
cout << dp[(1 << n) - 1] << '\n';
}