Vuelta atrás: La idea central de dar marcha atrás algoritmos aprender de la película El efecto mariposa

Vuelta atrás: De la película "El efecto mariposa> aprender idea central del algoritmo de retroceso

Sudoku, ocho reinas, 0-1 mochilas, dibujo coloreado, viajar problema del vendedor, problemas puede utilizar toda la gama

La comprensión de "retroceso"

Pensando, similar a la enumeración de búsqueda, la enumeración de todas las soluciones, encontrar soluciones para satisfacer las expectativas, con el fin de regular enumerar todas las soluciones posibles para el proceso de resolución de problemas se divide en varias etapas, cada etapa, se enfrentará a una tenedor en la carretera, sólo debes elegir la primera forma en que uno, encontrar el momento en que la carretera no tiene sentido (no cumple con las expectativas) de recurrir a un tenedor en la carretera, seleccionar otro.

Ocho reinas problema:

Hay un tablero de 8x8, llenarlo 8 piezas (Queen), donde cada pieza filas, columnas, diagonales no puede tener otra pieza

Este problema se divide en ocho etapas, seguido de los ocho piezas en la primera fila, segunda fila, ......, la octava fila, en el proceso de colocación, el non-stop para comprobar si la regla se cumple, si satisface el salto la siguiente línea continúan colocando las piezas, que no cumple con el intento de cambiar la ley una descarga

int[] result = new int[8];//全局或成员变量,下标表示行,值表示queen存储在哪一列
public void cal8queens(int row){   //调用方式:cal8queen(0);
	if(row == 8){   //8个棋子都放置好了打印结果
		printQueens(result);
		return;    //8个棋子都放好了,已经没法再往下递归了,所以就return
	}
	for(int column = 0 ; column < 8 ; ++column){  //每一行都有8种放法
		if(isOk(row,column)){  //有些放法不满足要求
			result[row] = column;   //第row行的棋子放到了column列
			cal8queens(row+1);   //考察下一行
		}
	}
}

private boolean isOk(int row , int column){  //判断row行column列放置是否合适
	int leftup = column - 1 , rightup = column + 1;
	for(int i = row - 1; i >= 0 ; --i){  //逐行往上考察每一行
		if(result[i] == column) return false;  //第i行的column列有棋子吗?
		if(leftup >= 0){   //考察左上对角线:第i行leftup列有棋子吗?
			if(result[i] == leftup) return false;
		}
		if(rightup < 8 ){  //考察右上对角线:第i行rightup列有棋子吗?
			if(result[i] == rightup)  return false;
		}
		--leftup ; ++rightup;
	}
	return true;
}

private void printQueens(int[] result){   //打印出一个二维矩阵
	for(int row = 0 ; row < 8 ; ++row){
		for(int column = 0 ;; column < 8 ; ++column){
			if(result[row] == column) System.out.print("Q ");
			else System.out.print("* ");
		}
		System.out.println():
	}
	System.out.println();
}

Aplicación de dos algoritmo backtracking clásico

1. 0-1 mochila

Una mochila, la mochila del peso total de la portadora WKG, tenemos n elementos, que van desde el peso de cada elemento, y indivisible, es deseable seleccionar varios elementos cargados mochila, se puede cargar en no más que el peso de la premisa de la mochila a continuación, cómo hacer que el peso total de los artículos más grandes de mochila?

Para n elementos, el método de instalación totales tiene 2^nespecies, quitar el peso total de la WKG más cercano, del resto del proceso de instalación, seleccione el peso total de los más cercanos WKG, ¿cómo puede no repetición exhaustiva de este 2^ntipo de método de instalación hacer?

El orden de los elementos de prioridad, todo el problema se descompone en n etapas, cada etapa correspondiente a la forma en un elemento de selección, un elemento que se procesa en la primera, cargado o no cargado en seleccionada, entonces el resto del artículo procesado de forma recursiva

Si encuentra que el peso de los artículos que han sido seleccionados por el WKG, parada continúan sondeando el resto del artículo

public int maxW = Integer.MIN_VALUE;//存储背包中物品总重量的最大值
//cw表示当前已经装进去的物品的重量和; i表示考察到哪个物品了;
//w背包重量 ; items表示每个物品的重量;n表示物品个数
//假设背包可承受重量100,物品个数10,物品重量存储在数组a中,那可以这样调用函数:
//f(0,0,a,10,100)
public void f(int i , int cw, int[] items , int n , int w){
	if(cw == w || i == n ){   // cw == w表示装满了;i== n表示已经考察完所有的物品
		if(cw  >  maxW) maxW = cw;
		return;
	}
	f(i+1 , cw , items , n ,w);
	if(cw + items[i] <= w){   //已经超过可以背包承受的重量的时候,就不要再装了
	f(i+1 , cw + items[i] , items ,n , w);
	}
}

2. Las expresiones regulares

Expresión regular, el más importante es un comodín, en el supuesto de expresión comprende regulares sólo *y ?dos comodines, en el que *cualquiera de la pluralidad de juego (mayor que o igual 0) cualquier carácter ?partidos cero o un carácter arbitrario, cómo backtracking determinar un texto dado, ya sea con la coincidencia de expresión regular?

Puede inspeccionar las expresiones regulares para cada carácter, el tiempo en que no comodín, haciendo coincidir directamente con los caracteres del texto, si el mismo proceso continúa hacia abajo, si es diferente, el retroceso

Si se encuentra con un carácter especial cuando, por ejemplo, *hay una variedad de programas de comparación, coincidirá con cualquier cadena de caracteres de texto, primero seleccione un esquema de emparejamiento aleatorio, seguir examinando el resto de los personajes

public class Pattern{
	private boolean matched = false;
	private char[] pattern;  //正则表达式
	private int plen;  //正则表达式长度
	
	public Pattern(char[] pattern , int  plen){
		this.pattern = pattern;
		this.plen = plen;
	}
	
	public boolean match(char[] text , int tlen){  //文本串及长度
		matched = false;
		rmatch(0,0,text,tlen);
		return matched;
	}
	
	private void rmatch(int ti,int pj, char[] text, int tlen){
		if(matched) return;//如何已经匹配了,就不需要继续递归了
		if(pj == plen){  //正则表达式到结尾了
			if(ti ==tlen) matched = true;//  文本串也到结尾了
			return;
		}
		if(pattern[pj] == "*"){   //*匹配任意个字符
			for(int k = 0 ; k <=  tlen-ti;++k){
				rmatch(ti+k,pj+1,text,tlen);
			}
		}else if (pattern[pj] == "?"){    //?匹配0个或者1个字符
			rmatch(ti,pj+1,text,tlen);
			rmatch(ti+1,pj+1,text,tlen);
		}else if(ti < tlen && pattern[pj] == text[ti]){   //纯字符匹配才行
			rmatch(ti+1,pj+1,text,tlen);
		}
	}
}
Publicado 75 artículos originales · ganado elogios 9 · vistas 9182

Supongo que te gusta

Origin blog.csdn.net/ywangjiyl/article/details/104717884
Recomendado
Clasificación