elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.
 
Inicio Ayuda Buscar Ingresar Registrarse
12 Febrero 2012, 23:06  

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


Desconectado Desconectado

Mensajes: 813


Aprendiendo de la vida


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

|-
ghastlyX
Colaborador
***
Desconectado Desconectado

Mensajes: 1.892



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
Og.


Desconectado Desconectado

Mensajes: 813


Aprendiendo de la vida


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

|-
O-LLOS-O


Desconectado Desconectado

Mensajes: 323


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
Og.


Desconectado Desconectado

Mensajes: 813


Aprendiendo de la vida


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

|-
ghastlyX
Colaborador
***
Desconectado Desconectado

Mensajes: 1.892



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 Respuesta Imprimir 

Ir a:  
Powered by SMF 1.1.16 | SMF © 2006-2008, Simple Machines