Ciao, questa soluzione utilizza un particolare tipo di dp, in cui la rappresentazione binaria dell’indice di ciascuno stato ti indica quali nodi sono già stati presi e quali no.
Per maggiore chiarezza, riscrivo il codice della soluzione ufficiale (solo il ciclo principale):
for (int mask=0;mask<(1<<n)-1;mask++) {
int left=-1;
for (int i=0;i<n;i++) {
if (!(mask & 1<<i)) {
left=i;
break;
}
}
for (int i=left;i<n;i++) {
if (!(mask & 1<<i)) {
int right=i;
int new_mask=mask | (1<<left) | (1<<right);
dp[new_mask]=max(dp[new_mask],dp[mask]+d[left][right]);
}
}
}
Quando si processa uno stato mask, si accede a stati il cui indice ha uno o due bit in più accesi (che si traduce in indici strettamente maggiori); questo garantisce che nel momento in cui si utilizza dp[mask] il suo valore è quello definitivo, visto che tutti gli stati da cui si “raggiunge” mask hanno indice minore.
Ciò detto, la transizione consiste nel trovare il primo nodo non ancora preso in quello stato ( left ) e provare ad accoppiarlo con ciascun nodo non ancora utilizzato ( right ). Siccome il grafo è completo (in particolare esiste sempre un arco da i a j con i<j, mendre l’arco da i a i ha ovviamente peso 0) sarà possibile provare ad aggiungere ciascun arco left → right (ricordando che left è il nodo non preso con minor indice).
Considerando di aggiungere l’arco left → right, possiamo provare a migliorare il risultato per lo stato mask | 2^{left} | 2^{right} (dove | è l’operatore bitwise or).
Quando right è uguale a left stiamo semplicemente considerando il caso in cui un nodo non viene utilizzato, cosa che succede se N è dispari.
Gli stati 0110 non vengono mai raggiunti dalla transizione di altri stati per il semplice fatto che si può accendere una coppia di bit se uno dei due è il primo non acceso. Questo non è un problema perché si ha uno stato equivalente con 0111, ovvero quando il primo nodo non è stato considerato, mentre sono stati presi il secondo è il terzo, oppure quando è stato preso l’arco dal primo al terzo e ignorato il secondo o se è stato preso l’arco dal primo al secondo e ignorato il terzo.
Spero di avere risposto alla tua domanda, scusa se mi sono dilungato sul funzinamento di questa dp, ma penso sia importante per capire la soluzione.