Programación algorítmica: unos problemillas

Iniciado por ghastlyX, 6 Septiembre 2008, 03:03 AM

0 Miembros y 1 Visitante están viendo este tema.

GroK

Buenas, ya he vuelto :D

Pues al final me he metido con el de grafos, me ha gustado mucho xD Y por cierto, decirte que me falto implementarle lo de varios casos por falta de tiempo, es decir, la entrada al programa es identica, solo que obvia el numero de casos y solo te resolvera el primero, si quieres probar otros casos hay que ejecutar de nuevo el programa (sorry, obviamente no presentaria eso asi en un concurso xDD)

Pero nada, queria que simplemente le echaras un vistazo a la parte principal del programa, el algoritmo y tal que es lo que importa al fin y al cabo, y ver que cambiarias tu o como lo harias (seguro que se puede hacer mas eficientemente que el mio :))

Aqui te lo dejo (Otra cosa, solo lo he hecho en pascal, en cuanto vuelva a tener un rato disponible intentare pasarlo a C a ver):

Código (pascal) [Seleccionar]
program circulos;

const
MAX = 20;

type
TValores  = Record
                Asignado : boolean;
Color       : boolean; { 'True' = Verde; 'False' = Amarillo }
End;
TVertices = array [0..MAX] of TValores;
TCasos = array [1..MAX] of TVertices;

var
nCasos : integer;
nVertices : integer;
nAristas : integer;
inicio, fin  : integer;
vertices : TVertices;
casos : TCasos;
flag : boolean;
i : integer;

procedure init_vertices (var c : TCasos);

var
i, j : integer;

begin

for i := 1 to MAX do
for j := 0 to MAX do
begin
c[i][j].Asignado := false;
c[i][j].Color := false;
end;

end;

function evalua (var v : TVertices; inicio, fin : integer) : boolean;

begin

if (v[inicio].Asignado = false) and (v[fin].Asignado = false) then { si ninguno ha sido asignado aun }
begin
v[inicio].Asignado := true;
v[inicio].Color := true;
v[fin].Asignado := true;
v[fin].Color := false;
evalua := true;
end
else
begin
if (v[inicio].Asignado) xor (v[fin].Asignado) then { si uno de los dos esta asignado }
begin
if v[fin].Asignado = false then
begin
v[fin].Asignado := true; { lo marcamos como coloreado }
v[fin].Color := not v[inicio].Color; { y le ponemos el color contrario al del otro vertice }
end
else
begin  { en caso de que el que no estuviese coloreado aun fuera el vertice inicial, lo mismo para este }
v[inicio].Asignado := true;
v[inicio].Color := not v[fin].Color;
end;
evalua := true;
end
else
begin  { si entramos aqui es porque ambos ya estan coloreados, comprobemos si es incompatible }
if v[inicio].Color = v[fin].Color then
evalua := false
else
evalua := true;
end;
end;

end;

{ -- MAIN --}

begin 

init_vertices (casos);
flag := true;
readln (nCasos);
readln (nVertices, nAristas);
for i := 1 to nAristas do
begin
readln (inicio, fin);
flag := flag and (evalua (vertices, inicio, fin));
end;
if flag then
writeln ('Miguel, a pintar')
else
writeln ('No pierdas el tiempo');

end.


Ale, ahi lo tienes, dispara :P

Decirte tambien que voy a estar fuera hasta el viernes o asi, en cuanto vuelva a estar online le meto mano al susodicho problema nº 2, y tal vez traducir este a C

Gracias de nuevo por tus problemas, de verdad que son muy interesantes y me he entretenido mucho con ellos, sobre todo el ultimo claro (pa haber salido de un examen de GRAFOS hoy mismo y ponerme a hacer problemas de GRAFOS... xDD hay que echarle ganas)

Saludos!
"I put on my Hendrix album and my son said 'Dad, who's that?' and i said 'Well son, that's God' "- Robert Plant


ghastlyX

Supongo que estará bien, Pascal no sé, por los comentarios que pones parece que está bien, pero no te lo puedo asegurar. He hecho en cinco minutillos una solución en C++ con comentarios en cada línea, así podrás ver si es lo mismo:
Código (cpp) [Seleccionar]
#include <iostream>
#include <vector>
using namespace std;

//Definimos los colores como constantes
const int VERDE = 0;
const int AMARILLO = 1;

bool dfs(vector<vector<int> >& grafo, int nodo, int color, vector<int>& color_nodo)
{
     bool flag = true;  //Declaramos el flag como true
     for(int i = 0; i < grafo[nodo].size(); i++)  //Mientras nuestro nodo tenga conexiones...
     {
             if(color_nodo[grafo[nodo][i]] == - 1) //Si el nodo al que está conectado no está pintado...
             {
                color_nodo[grafo[nodo][i]] = not color;  //Le ponemos el color contrario
                flag = dfs(grafo, grafo[nodo][i], not color, color_nodo);  //flag recibe el valor del DFS en dicho nodo
             }
             else if(color_nodo[grafo[nodo][i]] == color) return false;  //Si tiene el mismo color, es imposible el bicolouring, devolvemos false
     }
     return flag;  //Si no se ha salido antes, devuelve flag.
}             
     
int main()
{
    int q; //Número de casos
    cin >> q; //Recogemos los casos
    while(q--) //Mientras siga habiendo casos...
    {
            int n, p; //Nodos y conexiones respectivamente
            cin >> n >> p; //Recogemos ambos valores
            vector<int> color_nodo(n, -1); //Declaramos un arreglo de tamaño n para guardar el color de cada nodo
            vector<vector<int> > grafo(n); //Declaramos una matriz especificando solamente una dimensión
            while(p--) //Mientras haya conexiones por recoger...
            {
                 int origen, destino;   
                 cin >> origen >> destino;  //Recogemos los nodos de origen y destino
//Ambos nodos están conectados, por lo que hay que poner la conexión hacia ambos lados
//La matriz grafo indicará las conexiones: grafo[i].size() será la el número de conexiones donde cada j de grafo[i][j] es el nodo al que se conecta
                 grafo[origen].push_back(destino);  //Añadimos el nodo al que se conecta, en ambos sentidos
                 grafo[destino].push_back(origen);
            }
            color_nodo[0] = VERDE;  //Al primer nodo le asignamos color verde (puede ser al revés, es un simple número)
            if(dfs(grafo, 0, VERDE, color_nodo)) cout << "Miguel, a pintar" << endl;  //Hacemos DFS y según qué devuelva mostramos una salida u otra
            else cout << "No pierdas el tiempo" << endl;
    }
}


Venga, que seguro que más gente aparte de GroK sabe programar. Quiero una solución para el de las minas :P

Un saludo de ghastlyX ;)

ghastlyX

Pues ante la ausencia de respuestas, aclaro como se hace el de las minas. Recursivamente sería empezar en cada una de las casillas de la primera fila e ir probando cada camino desde ahí. Esto es terriblemente lento además de que probamos más de una vez el mismo camino. La solución es por DP.

Creamos una matriz de carácteres para guardar el mapa y otra del mismo tamaño para almacenar números. Entonces simplemente hay que recorrer dicha matriz: si en la posición hay una mina el número lo ponemos a un máximo declarado antes, de lo contrario será el mínimo entre el de arriba y las dos diagonales de arriba + 1. No hace falta decir que la primera fila ha de valer cero en todas las casillas excepto las que tengan minas. La solución final es el mínimo de todas las posiciones de la última fila.

No pondré más problemas, puesto que no tengo demasiado tiempo y casi nadie se pasa por aquí a resolverlos :P

Un saludo de ghastlyX ;)

Nakp

#13
jeje.. aqui va el mio de triángulos

#include <stdio.h>
#include <stdlib.h>

int main(){
int m, i, j;
scanf("%i",&m);
for(i = m; i >= 1; i--){
for(j = m; j >= i; j--){
printf("%i",i);
}
printf("\n");
}
getchar();
getchar();
return 0;
}


acabo de ponerme a hacerlos así que ya hago el de minas (ni lo he leido)

salu2
Ojo por ojo, y el mundo acabará ciego.

Nakp

Cita de: ghastlyX en 21 Septiembre 2008, 21:50 PM
Pues ante la ausencia de respuestas, aclaro como se hace el de las minas. Recursivamente sería empezar en cada una de las casillas de la primera fila e ir probando cada camino desde ahí. Esto es terriblemente lento además de que probamos más de una vez el mismo camino. La solución es por DP.

Creamos una matriz de carácteres para guardar el mapa y otra del mismo tamaño para almacenar números. Entonces simplemente hay que recorrer dicha matriz: si en la posición hay una mina el número lo ponemos a un máximo declarado antes, de lo contrario será el mínimo entre el de arriba y las dos diagonales de arriba + 1. No hace falta decir que la primera fila ha de valer cero en todas las casillas excepto las que tengan minas. La solución final es el mínimo de todas las posiciones de la última fila.

No pondré más problemas, puesto que no tengo demasiado tiempo y casi nadie se pasa por aquí a resolverlos :P

Un saludo de ghastlyX ;)

ahm... que se me hace que se resuelve con una matriz de adyacencia :xD deja un rato libre que no se queda sin solución
Ojo por ojo, y el mundo acabará ciego.

ghastlyX

¿Matriz de adyacencia? No es de grafos el problema, es de DP y se resuelve como expliqué en el post anterior, supongo que pensarías en BFS o Dijkstra, pero va de dinámica.

Un saludo de ghastlyX ;)

Nakp

Cita de: ghastlyX en 25 Septiembre 2008, 19:44 PM
¿Matriz de adyacencia? No es de grafos el problema, es de DP y se resuelve como expliqué en el post anterior, supongo que pensarías en BFS o Dijkstra, pero va de dinámica.

Un saludo de ghastlyX ;)

en realidad se me ocurrió warshall pero apenas lo entiendo :¬¬ y en 6 horas tengo un control de lectura! :laugh:
Ojo por ojo, y el mundo acabará ciego.

ghastlyX

Pues no te sé decir si por Floyd-Warshall funcionaría, pero si no me equivoco creo que mediante ese algoritmo tienes complejidad cúbica, tal y como he explicado sólo cuadrática. Olvida algoritmos de búsquedas de caminos en grafos para este problema. De hecho, olvida los grafos para este problema, se puede resolver sin haber visto un grafo en la vida.

Un saludo de ghastlyX ;)

juancho77

CitarCreamos una matriz de carácteres para guardar el mapa y otra del mismo tamaño para almacenar números. Entonces simplemente hay que recorrer dicha matriz: si en la posición hay una mina el número lo ponemos a un máximo declarado antes, de lo contrario será el mínimo entre el de arriba y las dos diagonales de arriba + 1. No hace falta decir que la primera fila ha de valer cero en todas las casillas excepto las que tengan minas. La solución final es el mínimo de todas las posiciones de la última fila.

Ya que estamos. Me tome el trabajo de pasar el algortimo a Java  :-*
Código (java) [Seleccionar]

import java.io.*;
import java.util.Random;
public class minas {
    public static void main() throws Exception {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        char[][] caracteres;
        int [][] resultado;
        System.out.print("Ingrese cantidad de filas:");
        int filas=Integer.parseInt(br.readLine());
        System.out.print("Ingrese cantidad de columnas:");
        int columnas=Integer.parseInt(br.readLine());
        caracteres=new char[filas][columnas];
        resultado=new int[filas][columnas];
        Random rnd=new Random();
        for (int i=0; i<filas; i++)
        {
            for(int j=0;j<columnas;j++)
            {
                //genero la tabla/////////////
                int aleat=rnd.nextInt(2);
                if (aleat==1)
                    caracteres[i][j]='M';
                    else caracteres[i][j]='L';
                //////////////////////////////
                //
                if (caracteres[i][j]=='M')
                    resultado[i][j]=99;
                else //si esta libre
                {
                    if (i==0) //si es la primera fila
                        resultado[i][j]=0;
                    else //en cualquier otro caso
                    {
                        if ((j>0)&&(j<columnas-1))
                            resultado[i][j]=min(resultado[i-1][j-1]+1,resultado[i-1][j],resultado[i-1][j+1]+1);
                        else if (j==0)
                            resultado[i][j]=min(resultado[i-1][j],resultado[i-1][j+1]+1,99);
                             else
                               resultado[i][j]=min(resultado[i-1][j],resultado[i-1][j-1]+1,99);
                            }           
                        }       
            }
        }
        int menor=99;
        for (int j=0; j<columnas;j++)
            if (resultado[filas-1][j]<menor)
                menor=resultado[filas-1][j];
        if (menor==99)
            System.out.println("Yum Yum");
            else System.out.println(menor);
}
    public static int min(int num1, int num2, int num3){
        int menor=num1;
        if (num2<num1)
            menor=num2;
        if (num3<menor)
            menor=num3;
        return menor;
    }
}