2010-07-16 15 views
19

Tengo pocos puntos cartesianos de la forma: (x, y)
donde xey son ambos enteros no negativos.Algoritmo para organizar puntos cartesianos

Por ej.
(0,0), (1,1), (0,1)

Necesito un algoritmo para disponer los puntos anteriores
de tal manera que va de un punto a otros
cambios ya sea x o y por 1.

En otras palabras, me gustaría evitar
movimiento diagonal.

Por lo tanto, los puntos mencionados anteriormente se organizarán como:
(0,0), (0,1), (1,1).

Similarmente para (0,0), (1,1), (0,2)
no hay tal disposición posible.

No estoy seguro acerca de cómo llamarlo
pero yo diría que es Manhattan ordenar.

¿Alguien puede ayudar?

+1

Pregunta aseada. +1 – Cam

+1

¿Siempre comienzas desde 0,0 (o el punto inferior izquierdo)? ¿O puedes comenzar desde cualquier punto? – cape1232

+0

me gusta la pregunta, pero tendría que especificar detalles, por ejemplo, ¿va horizontal primero (intente encontrar un punto con x valor +1 pero el mismo valor y como el punto actual) o vertical? ¿Qué pasa si dos puntos son iguales? puedes ir hacia atrás? es decir, de (2,2) a (2,1)? –

Respuesta

12

Si usted está buscando un arreglo que no repita vértices:

Lo que parece estar en busca de un camino hamiltoniano en un gráfico de la red.

Esto se sabe que es NP-completo para Grid Graphs general, vea Hamilton Paths in Grid Graphs.

Probablemente pruebe suerte con cualquiera de los algoritmos aproximados/heurísticos/etc conocidos para Hamiltonian Path/Euclidean Traveling Salesman Problem.


Si usted está buscando un arreglo que puede repetir, pero quiere que el mínimo número posible de puntos en la disposición:

Esto es de nuevo NP-completo. El problema anterior se puede reducir a eso. Esto se debe a que la caminata mínima posible tiene n vértices si y solo si el gráfico tiene una ruta hamiltoniana.


Si estás en busca de un arreglo de puntos,

Entonces todo lo que tiene que hacer es comprobar si está conectado el gráfico. Si no está conectado, no puede haber tal arreglo.

Puede hacer una primera búsqueda en profundidad para descubrirlo. La primera búsqueda en profundidad también le dará esa disposición en caso de que el gráfico esté conectado.

Si quiere algo más cerca de lo óptimo (pero en un tiempo razonablemente rápido), probablemente pueda usar algoritmos de aproximación para el problema de Euclidean Traveling Salesman.

1

Esto podría simplificarse ya que se minimiza la distancia entre cada punto consecutivo. Pasar de (0,0) a (0,1) es simplemente 1 unidad, pero pasar de (0,0) a (1,1) es en realidad sqrt (2). Entonces, si organiza los puntos en un gráfico y luego realiza un recorrido mínimo de distancia total total (vendedor ambulante), debe organizarlos correctamente.

Editar: Si nunca desea un paso que sea mayor que 1, simplemente no agregue ningún borde que sea mayor que 1. El cruce seguirá funcionando correctamente, e ignorará las rutas que requieran un movimiento> 1.

Edición 2: Para aclarar aún más, puede usar cualquier algoritmo de selección de bordes que desee. Si estás de acuerdo moviendo 2 espacios, siempre y cuando el espacio no sea diagonal, puedes optar por poner un borde entre (0,2) y (0,4). El algoritmo de distancia mínima seguirá funcionando. Simplemente coloque los bordes de una manera inteligente, y puede usar cualquier número de criterios de selección para determinar el resultado.

+1

alguien borró un comentario que fue bastante bueno; el orden (0,0) -> (1,1) -> (5,0) es válido en sus criterios, pero no el suyo. – nlucaroni

+0

@nlucaroni Actualicé mi respuesta para mostrar lo que estaba pensando en términos de esa situación particular. Es bastante fácil evitar esa situación al controlar qué bordes se dibujan realmente y mantener intacto el algoritmo de recorrido básico. – drharris

+1

no. No creo que nadie te sugiera que vayas más grande que uno. El problema no es entrar en diagonales. esos tres puntos que menciono, aunque no tienen un pedido especificado bajo los criterios de los autores. pero una lista como esta sería más adecuada para la discusión, (3,2) -> (0,2) -> (0,3) -> (1,3). Aquí, aunque el paso (3,2) -> (1,3) sería mínimo, se debe evitar. – nlucaroni

0

Una forma de hacerlo es crear dos listas ordenadas de las coordenadas. Uno ordenado por x y uno ordenado por y. Luego, recursivamente encuentra una solución.

Viene el código (no estoy seguro de qué idioma aún, tal vez pseudocódigo?) ... Editar - no importa, ya que mi respuesta no es tan buena como algunas de las demás de todos modos.

4

Puede construir un gráfico con los vértices siendo sus puntos, y los bordes son los pasos válidos.

Lo que estás buscando es un Hamiltonian path para este gráfico. Esto, en su forma general, es un problema NP-completo, lo que significa que no hay una solución eficiente conocida (es decir, una que se adapte bien al número de puntos). Wikipedia describe un randomized algorithm que es "rápido en la mayoría de los gráficos" y podría ser de utilidad:

de inicio desde un vértice al azar, y continuar si hay un vecino no visitado.Si no hay más vecinos no visitados, y la ruta formada no es hamiltoniana, elija a un vecino uniformemente al azar, y rote usando ese vecino como pivote. (Es decir, agregue un borde a ese vecino y elimine uno de los bordes existentes de ese vecino para no formar un bucle). Luego, continúe con el algoritmo en el nuevo final de la ruta.

Sin embargo, una solución más eficiente podría existir para esta situación particular.

+0

-1: Usted ha demostrado que Hamiltonian Path es más difícil que resolver este problema. No ha demostrado que el problema actual sea NP-Complete. –

+0

Tienes razón, estoy corregido. Editado – Thomas

+0

Se ha eliminado el -1. –

2

Piense en ello como un gráfico donde cada nodo tiene como máximo cuatro bordes. Luego haga una búsqueda de profundidad/amplitud.

+0

Es muy probable que sea la respuesta correcta porque la pregunta no dice nada sobre optimalidad o similar. –

0

¿Qué tal una rutina recursiva de fuerza bruta REXX ... Intente todas las posibles rutas e imprima las que funcionen. sesión

/* rexx */ 
point. = 0 /* Boolean for each existing point */ 
say 'Enter origin x and y coordinate:' 
pull xo yo 
point.xo.yo = 1 /* Point exists... */ 
say 'Enter destination x and y coordinate:' 
pull xd yd 
point.xd.yd = 1 /* Point exists... */ 
say 'Enter remaining x and y coordinates, one pair per line:' 
do forever 
    pull x y 
    if x = '' then leave 
    point.x.y = 1 
end 

path = '' 
call findpath xo yo path 
say 'All possible paths have been displayed' 
return 

findpath: procedure expose point. xd yd 
arg x y path 
if \point.x.y then return    /* no such point */ 
newpoint = '(' || x y || ')' 
if pos(newpoint, path) > 0 then return /* abandon on cycle */ 
if x = xd & y = yd then     /* found a path */ 
    say path newpoint 
else do         /* keep searching */ 
    call findpath x+1 y path newpoint 
    call findpath x-1 y path newpoint 
    call findpath x y+1 path newpoint 
    call findpath x y-1 path newpoint 
    end 
return 

Ejemplo:

Path.rex 
Enter origin x and y coordinate: 
0 0 
Enter destination x and y coordinate: 
2 2 
Enter remaining x and y coordinates, one pair per line: 
0 1 
1 1 
2 1 
1 2 

(0 0) (0 1) (1 1) (2 1) (2 2) 
(0 0) (0 1) (1 1) (1 2) (2 2) 
All possible paths have been displayed 

no intenta esto en algo grande, aunque - podría tomar un tiempo muy largo! Pero luego la pregunta nunca mencionó nada acerca de ser una solución óptima.

Cuestiones relacionadas