Skip to Content

Grouping

Análisis no oficial (C++) 

Explicación

Definimos dp[i]dp[i] como el puntaje máximo posible para el subconjunto de conejos representado por la máscara ii.

La transición involucra dos pasos para cada máscara ii:

  1. Puntaje base: Inicializamos dp[i]dp[i] calculando la suma de aj,ka_{j,k} para todos los pares (j,k)(j, k) dentro de la máscara. Esto asume que todos los conejos de la máscara forman un solo grupo.
  2. Fusión de subconjuntos: Mejoramos dp[i]dp[i] partiendo la máscara en dos submáscaras disjuntas jj e iji \oplus j. La transición es:
dp[i]=maxji(dp[i],dp[j]+dp[ij]) dp[i] = \max_{j \subseteq i} \left(dp[i], dp[j] + dp[i \oplus j] \right)

Implementación

Complejidad temporal: O(3N+N22N)\mathcal{O}(3^N + N^2 \cdot 2^N)

#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'; }