elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.
 
Inicio Ayuda Ingresar Registrarse
14 Marzo 2010, 12:20  


Temas destacados: Últimos eventos sobre seguridad/inseguridad


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderador: Eternal Idol)
| | |-+  Espirales.cpp (problema de OMI), optimizacion?
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Imprimir
Autor Tema: Espirales.cpp (problema de OMI), optimizacion?  (Leído 503 veces)
Np-アクス

Desconectado Desconectado

Mensajes: 635


se libre... se tu


Ver Perfil
Espirales.cpp (problema de OMI), optimizacion?
« en: 23 Diciembre 2009, 07:01 »

Hola!
bueno, tengo que hacer este problema:


y realize este codigo:
Código
#include <iostream>
 
struct acSTR
{
   int cuadro[1000][1000];
};
 
void check(unsigned long long *cont, acSTR &scene, int dir, int x, int y, int pasx, int pasy)
{
   int copy[y][x], i, j;
   scene.cuadro[pasy][pasx] = 1;
   *cont += 1;
   for(i=0;i<y;i++)
       for(j=0;j<x;j++)
           copy[i][j] = scene.cuadro[i][j];
   switch(dir)
   {
       case 00:
           if(scene.cuadro[pasy][pasx+1]==-1)
           {
               check(cont, scene, dir, x, y, pasx+1, pasy);
               for(i=0;i<y;i++)
                   for(j=0;j<x;j++)
                       scene.cuadro[i][j] = copy[i][j];
           }
           if(scene.cuadro[pasy+1][pasx]==-1)
           {
               dir = 01;
               check(cont, scene, dir, x, y, pasx, pasy+1);
               for(i=0;i<y;i++)
                   for(j=0;j<x;j++)
                       scene.cuadro[i][j] = copy[i][j];
           }
       break;
       case 01:
           if(scene.cuadro[pasy+1][pasx]==-1)
           {
               check(cont, scene, dir, x, y, pasx, pasy+1);
               for(i=0;i<y;i++)
                   for(j=0;j<x;j++)
                       scene.cuadro[i][j] = copy[i][j];
           }
           if(scene.cuadro[pasy][pasx-1]==-1)
           {
               dir = 10;
               check(cont, scene, dir, x, y, pasx-1, pasy);
               for(i=0;i<y;i++)
                   for(j=0;j<x;j++)
                       scene.cuadro[i][j] = copy[i][j];
           }
       break;
       case 10:
           if(scene.cuadro[pasy][pasx-1]==-1)
           {
               check(cont, scene, dir, x, y, pasx-1, pasy);
               for(i=0;i<y;i++)
                   for(j=0;j<x;j++)
                       scene.cuadro[i][j] = copy[i][j];
           }
           if(scene.cuadro[pasy-1][pasx]==-1)
           {
               dir = 11;
               check(cont, scene, dir, x, y, pasx, pasy-1);
               for(i=0;i<y;i++)
                   for(j=0;j<x;j++)
                       scene.cuadro[i][j] = copy[i][j];
           }
       break;
       case 11:
           if(scene.cuadro[pasy-1][pasx]==-1)
           {
               check(cont, scene, dir, x, y, pasx, pasy-1);
               for(i=0;i<y;i++)
                   for(j=0;j<x;j++)
                       scene.cuadro[i][j] = copy[i][j];
           }
           if(scene.cuadro[pasy][pasx+1]==-1)
           {
               dir = 00;
               check(cont, scene, dir, x, y, pasx+1, pasy);
               for(i=0;i<y;i++)
                   for(j=0;j<x;j++)
                       scene.cuadro[i][j] = copy[i][j];
           }
       break;
   }
}
 
int main()
{
   unsigned long long count = 0;
   int x, y, i, j;
   std::cin >> y >> x;
   acSTR cuadro;
   for(i=0;i<y;i++)
       for(j=0;j<x;j++)
           cuadro.cuadro[i][j]=-1;
   check(&count, cuadro, 00, x, y, 0, 0);
   std::cout << count%1000000000 ;
   return 0;
}
 

el codigo funciona en cualquier caso, pero el problema es que si M y N <= 10 no pasa de un segundo en encontrar la solucion, pero si le pongo mas, se tarda mas de un segundo en hayar la respuesta :P
he aqui mi duda:

Como optimizarian este codigo para que en casos de 100 * 100 tardase menos de un segundo en encontrar todas las posibles espirales?


Saludos :D
En línea

Preparandome para la OMI =D
por si necesitas un buen hosting gratuito: Aqui

ghastlyX
Ex-Staff

Desconectado Desconectado

Mensajes: 1.803


No es posible conseguir nada sin arriesgarse algo


Ver Perfil
Re: Espirales.cpp (problema de OMI), optimizacion?
« Respuesta #1 en: 23 Diciembre 2009, 18:12 »

He mirado y probado tu código por encima y supongo que habrás hecho un backtracking. La cuestión no es optimizar tu código, sinó resolver el problema de otra forma mucho más eficiente.

Mirándolo por encima, una solución trivial sería algo así:
Código
#include <iostream>
#include <vector>
using namespace std;
 
long long M[1000][1000];
 
long long f(int n, int m) {
   if (M[n][m] == -1) {
       if (M[m][n] != -1) return M[n][m] = M[m][n];
       M[n][m] = n*m%1000000000;
       for (int i = 1; i <= n - 1; ++i)
           for (int j = 1; j <= m - 1; ++j)
               M[n][m] = (M[n][m] + f(i,j))%1000000000;
   }
   return M[n][m];
}
 
int main() {
   int n, m;
   cin >> n >> m;
   for (int i = 0; i < 1000; ++i) for (int j = 0; j < 1000; ++j) M[i][j] = -1;
   cout << f(n, m)%1000000000 << endl;
}

Que creo que es correcta y debe funcionar mucho más rápido que la tuya, aunque para casos grandes no será suficiente rápida. Pero probablemente la recurrencia tan evidente que he puesto en mi código se pueda simplificar algo más.

Un saludo de ghastlyX ;)
En línea
Np-アクス

Desconectado Desconectado

Mensajes: 635


se libre... se tu


Ver Perfil
Re: Espirales.cpp (problema de OMI), optimizacion?
« Respuesta #2 en: 23 Diciembre 2009, 18:58 »

wow, que solucion tan eficiente   :o

en el caso de 250 * 250 se tarda mas de un segundo, pero 250 * 250 en tu programa es mas rapido que 20 * 20 en el mio  :xD

voy a depurarlo haber como funciona  ;D

Gracias por la ayuda  :)
En línea

Preparandome para la OMI =D
por si necesitas un buen hosting gratuito: Aqui

O-LLOS-O

Desconectado Desconectado

Mensajes: 264


tengo 14 invitaciones para locker-z enviar mp


Ver Perfil
Re: Espirales.cpp (problema de OMI), optimizacion?
« Respuesta #3 en: 23 Diciembre 2009, 19:43 »

awesome.... sorry por no aportar nada simplemente
En línea

Enrikz

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Re: Espirales.cpp (problema de OMI), optimizacion?
« Respuesta #4 en: 24 Diciembre 2009, 02:50 »

Código
#include <iostream>
#include <vector>
using namespace std;
 
int M[255][255];
 
int f(int n, int m) {
   if (M[n][m] == -1) {
       if (M[m][n] != -1) return M[n][m] = M[m][n];
       M[n][m] = n*m;
       for (int i = 1; i <= n - 1; ++i)
           for (int j = 1; j <= m - 1; ++j)
               M[n][m] = (M[n][m] + f(i,j))%1000000000;
   }
   return M[n][m];
}
 
int main() {
   int n, m;
   cin >> n >> m;
   for (int i = 0; i < 255; ++i) for (int j = 0; j < 255; ++j) M[i][j] = -1;
   cout << f(n, m)%1000000000 << endl;
}
 

Optimizando el codigo de GhastlyX he conseguido que enlugar de 53 seg para el 250x250 ahora tarde 17.841

Aunque aun demasiado!
En línea
Enrikz

Desconectado Desconectado

Mensajes: 6


Ver Perfil
Re: Espirales.cpp (problema de OMI), optimizacion?
« Respuesta #5 en: 24 Diciembre 2009, 03:13 »

Mi version en O(n^2) usando un poco de matematicas y combinatoria, es decir que hace el caso de 1000 x 1000 en 0.05 segundos.

Código
#include <iostream>
using namespace std;
const int M = 2009; //el doble del tamaNo maximo
int DP[M][M];
const int MOD = 1000000000;
 
int main() {
   int n, m;
   for (int i=0;i<M;++i) DP[i][0]=DP[i][i]=1;
   for (int i=2;i<M;i++) for(int j=1;j<i;j++)  
       DP[i][j] = (DP[i-1][j-1]+DP[i-1][j])%MOD;
   while (cin >> n >> m) cout << (DP[n+m][m]+MOD-1)%MOD << endl;
}
 

En todos los casos que he probado (grandes) da la misma salida que el programa de GhastlyX.
« Última modificación: 24 Diciembre 2009, 03:34 por Enrikz » En línea
Np-アクス

Desconectado Desconectado

Mensajes: 635


se libre... se tu


Ver Perfil
Re: Espirales.cpp (problema de OMI), optimizacion?
« Respuesta #6 en: 24 Diciembre 2009, 06:11 »

ok...
increible xD
literalmente haces:

1
1    1
1    2    1
1    3    3    1
1    4    6    4     1
1    5    10  10   5    1
1    6    15  20   15  6    1

etc...
y despues

sacas el valor asi:
Código:
cout << (DP[n+m][m]+MOD-1)%MOD

pero lo que no entiendo es como calculaste que ese iva a ser el numero de espirales  :huh:

me podrian explicar o algo xD
yo, mi código lo hize con recurcion buscando y contando cada posible espiral en el cuadro pero ustedes lo hacen calculándolo matemáticamente xD
En línea

Preparandome para la OMI =D
por si necesitas un buen hosting gratuito: Aqui

ghastlyX
Ex-Staff

Desconectado Desconectado

Mensajes: 1.803


No es posible conseguir nada sin arriesgarse algo


Ver Perfil
Re: Espirales.cpp (problema de OMI), optimizacion?
« Respuesta #7 en: 24 Diciembre 2009, 09:43 »

Estuvimos hablando, hizo los primeros casos 1xn, 2xn, 3xn... y vio que seguían ese patrón con mi código.

Ahora a las 10.00 hora española, de aquí a unos 20 minutos, hay un concurso de entrenamiento online en la página de la OIE (Olimpiada Informática Española), abierto a todo el mundo. Si te estás entrenando para la OMI y te apetece puedes participar.

http://www.olimpiada-informatica.org/

Un saludo de ghastlyX ;)
En línea
Páginas: [1] Ir Arriba Imprimir 
Ir a:  





Consolas     La Web de Goku     MilW0rm     MundoDivx

Hispabyte     Truzone     TodoReviews     ZonaPhotoshop

Yashira.org    Videojuegos    indetectables.net    Seguridad Informatica Colombia    Indejuegos    Internet móvil

Noticias Informatica    Seguridad Informática    ADSL    eNYe Sec    Seguridad Wireless    Underground México    Biblioteca de Seguridad

Todas las webs afiliadas están libres de publicidad engañosa.

Powered by SMF 1.1.11 | SMF © 2006-2008, Simple Machines LLC