[Pregunta Solución] Kronican

El título describe que
Mislav tiene N tazas de volumen infinito, y cada taza contiene algo de agua. Mislav quería beber toda el agua, pero no quería beber más que K vasos de agua. Todo lo que puede hacer Mistrav es verter agua de una taza a otra. Desafortunadamente, es importante para Mislav elegir qué dos tazas verter, porque no todas las tazas están tan lejos de él. Más precisamente, el precio que se paga por verter agua del vaso i al vaso j es Cij. Ayuda a Mislav a encontrar el valor mínimo del precio total que debe pagar.

Formato de entrada La
primera línea de entrada contiene los números enteros N y K (1≤K≤N≤20). Indica el número total de vasos para beber y el número máximo de vasos que puede beber Mislav. Cada una de las siguientes N filas contiene N números enteros Cij (0≤Cij≤1e5). El j-ésimo entero en la fila i + 1º representa el costo de verter agua de la i-ésima taza y la j-ésima taza. Asegúrese de que Cii sea igual a 0.

Formato de
salida Muestra un número entero. Representa el valor mínimo del costo total que Mislav debe pagar.

Ejemplo
Ejemplo de entrada 1
3 3
0 1 1
1 0 1
1 1 0
Ejemplo de salida 1
0
Ejemplo de entrada 2
3 2
0 1 1
1 0 1
1 1 0
Ejemplo de salida 2
1
Ejemplo de entrada 3
5 2
0 5 4 3 2
7 0 4 4 4
3 3 0 1 2
4 3 1 0 5
4 5 5 5 0
Salida de muestra 3
5
Rango
n <= 20

Porque ves n <= 20 n <= 20norte<=2 0 , generalmente solo presione la forma,
luego use2 n 2 ^ ndirectamente2Los estados n 01 indican si hay agua en una taza determinada.
Cada vez que enumera una taza con agua y luego enumera una taza con agua, vierta la taza frontal en la parte posterior para completar la transferencia.
Tiempo complejidadO (2 n ∗ norte 2) O (2 ^ norte * norte ^ 2)O ( 2nortenorte2 )
Entonces letle tlet l e
Así que piensa en un pequeño truco, cada vez que solo se
pasaenumerando todo el "1" en el estado

Código:

#pragma GCC optimize ("-Ofast")
#include <bits/stdc++.h>
#define maxn 25
#define maxm 2000010
using namespace std;
int n, m, w[maxn][maxn], pos[maxm], power[maxn], num[maxm], dp[maxm];

inline int read(){
    
    
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

int lowbit(int x){
    
     return x & -x; }

int main(){
    
    
	freopen("pb.in", "r", stdin);
	freopen("pb.out", "w", stdout);
	n = read(), m = read();
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			w[i][j] = read();
	power[0] = 1, pos[1] = 1;
	for (int i = 1; i <= n; ++i) power[i] = power[i - 1] << 1, pos[power[i]] = i + 1;
	for (int i = 0; i < power[n]; ++i)
		for (int j = i; j; j -= lowbit(j)) ++num[i];
	for (int i = 0; i < power[n]; ++i) dp[i] = 1e9;
	dp[power[n] - 1] = 0;
	int ans = 1e9;
	for (int i = power[n] - 1; i >= 0; --i){
    
     //printf("num[%d]=%d\n", i, num[i]);
		if (num[i] <= m) ans = min(ans, dp[i]);
		for (int s1 = i; s1; s1 -= lowbit(s1)){
    
    
			int j = pos[lowbit(s1)];
			for (int s2 = i; s2; s2 -= lowbit(s2)){
    
    
				int k = pos[lowbit(s2)];
				if (j != k) dp[i ^ power[j - 1]] = min(dp[i ^ power[j - 1]], dp[i] + w[j][k]);
			}
		}
	}
	printf("%d\n", ans);
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/ModestCoder_/article/details/108617938
Recomendado
Clasificación