Viajar (estado comprimido, clásico problema del vendedor ambulante)

Después de la codificación de tantos días, Sr. Acmer quiere tener una buena rest.So viajar es la mejor opción! Ha decidido visitar n ciudades (que insiste en ver todas las ciudades! Y que no le importa en qué ciudad siendo su estación de salida, porque Superman le puede aportar a cualquier ciudad en un primer momento, pero sólo una vez.), y por supuesto hay m carreteras aquí, siguiendo una cuota como usual.But Sr. Acmer se aburre con tanta facilidad que él no quiere visitar una ciudad más de dos veces ! Y él es tan mala que quiere minimizar el costo total! él es perezoso que see.So que se dirige a ti en busca de ayuda.

Entrada

Hay varios casos de prueba, la primera línea es de dos números enteros n (1 <= n <= 10) y m, lo que significa que tiene que visitar n ciudades y hay m caminos que puede elegir, entonces m líneas siguientes, cada línea incluyen tres números enteros a, b y c (1 <= a, b <= n), significa que hay un camino entre a y B y el coste es por supuesto c.Input al final del archivo.

Salida

Salida de la cuota mínima que debe pagar, o -1 si no puede encontrar una ruta tal.

 

Ejemplo de entrada

2 1

1 2 100

3 2

1 2 40

2 3 50

3 3

1 2 3

1 3 4

2 3 10

Ejemplo de salida

100

90

7

 

efecto tema: una persona ir a la gira de N de la ciudad, se puede partir de cualquier ciudad, hay m carretera entre las ciudades, el costo de cada camino tiene que hacer, resuelto a través de todas las ciudades, y cada ciudad visitada no más de dos veces el costo mínimo

Ideas: hemos estado en X número de ciudades, y el número de veces que un número X de ciudades son visitadas, y actualmente se encuentra en la ciudad como un estado, como punto de partida a la ciudad actual fue a otras ciudades para tratar de actualizar el estado de los costes mínimos correspondientes pero el número de estas ciudades han estado en este estado a cómo almacenarlo, abra una matriz n-dimensional es claramente poco realista, esta vez, pensamos que codifica la compresión se puede aplicar a otro:

En línea con el número de preguntas de cada ciudad sólo tres no han sido visitados, estado allí una vez, he estado allí dos veces, por lo que un número ternario se puede almacenar el estado de una ciudad, a continuación, n bits Tres sistema de números se puede almacenar el estado n ciudades, suponemos que el número ternario X, para la ciudad i bit i TRIT por lo tanto, el número de ciudades visitadas i es igual a X / (3 ^ i)% 3

Por lo tanto, podemos concluir fórmula recursiva:

Hombre para mí: dp [i] [j] = min (dp [i] [j], dp [i-3 ^ j] [v] + w [v] [j]) 

One for All: dp [i + 3 ^ v] = min (dp [i + 3 ^ v] [v], dp [i] [j] + w [j] [v])

 

Este problema se ha encontrado con un problema, olvidando la diferencia entre la función de llenado y MEMEST, memset se asigna byte a byte, empecé a usar INF = 999999, los resultados han conducido al error, por lo que si una cesión general por 1 y 0

Con el código:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define INF 0x3f    
#define check(x,y) (x/tab[y])%3   //获取状态X中,到达Y城市的次数 
using namespace std;
int tab[11]= {1},dp[60000][11];  //tab数组存储#3的次方数 
int main() {
	int n,m;
	for(int i=1; i<=10; i++) {   //初始化tab数组 
		tab[i]=tab[i-1]*3;
	}
	while(cin>>n>>m) {
		int w[11][11],cost=0x3f3f3f3f;
		memset(w,INF,sizeof(w));
		memset(dp,INF,sizeof(dp));     //初始化为无穷大 
		int x,y,wi;
		for(int i=0; i<m; i++) {
			cin>>x>>y>>wi;
			x--;
			y--;     //城市编号转化成 0开始 
			w[x][y]=w[y][x]=min(w[x][y],wi);
		}
		for(int i=0; i<n; i++)dp[tab[i]][i]=0;  //初始化从每个城市出发的情况,保证每种状态都能遍历到 
		for(int i=1; i<tab[n]; i++) {
			bool flag=true;   //设置标志flag,如果 i 状态下,去过了 n个城市,则可以尝试更新最小花费 
			for(int j=0;j<n;j++){
				
				if(check(i,j)==0){  
					flag=false;  //i 状态下 j 城市没有去过 
					continue;
				}
				for(int v=0;v<n;v++){
					if(check(i,v)==2)continue;  //如果 i 状态下 v城市已经访问了两次跳过 v 城市 
					dp[i+tab[v]][v]=min(dp[i+tab[v]][v],dp[i][j]+w[j][v]);  //我为人人递推 
				}
			}
			if(flag){  //0~n-1城市都有去过 
				for(int j=0;j<n;j++){
					cost=min(cost,dp[i][j]);  //尝试更新最小花费 
				}
			}
		}
		if(cost==0x3f3f3f3f)cost=-1;  //如果不能完成遍历所有城市的目标 
        cout<<cost<<endl;
       // printf("%d\n",cost);
	}
	return 0;
}

 

Publicado 42 artículos originales · alabanza ganado 16 · vistas 3400

Supongo que te gusta

Origin blog.csdn.net/qq_41542638/article/details/102704149
Recomendado
Clasificación