[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [obm-l] Algoritmos



O problema reverso, de ter que descobrir qual carta sobra, dado o número
de cartas é uma especialização do "Josephus Problem".

Vejam em http://library.wolfram.com/examples/josephusproblem

No caso do Josephus Problem o movimento é invertido e movimentam-se várias
cartas. Retira-se a primeira carta e coloca-se n cartas em baixo do monte.
(No problema da Fernanda, coloca-se *uma* carta em baixo do monte e
retira-se a primeira)

Bom, isso é só curiosidade. É que resolvi o problema da Fernanda
utilizando o problema reverso. Escrevi um programa de computador que
calculava a carta que sobra para pilhas de diversos tamanhos até encontrar
a resposta. As duas primeiras pilhas em que sobram a carta 2001 são de
tamanho 2095 e 6191, mas como se quer uma de tamanho menor que 5000, a
solução é 2095

Eu poderia ter feito o programa simulando os movimentos, mas, para um dado
n, a complexidade seria O(n^2). Considerando que se calculava para todos
os primeiros valores até encontrar a solução, a complexidade seria
O(s^3), onde s é o valor da solução. Isso é proibitivo para valores
altos como 2001.

Dessa forma me baseei na recorrência
T(n) = n       , se T(n-1)==1
T(n) = T(n-1)-1, caso contrário
T(1) = 1
T(n) significa a carta que sobra em uma pilha de n cartas.
Observe que se temos uma pilha [1,..,n], ao se realizar o movimento do
problema, teremos uma pilha [n,1,...,n-2], que tem n-1 elementos,
reduzindo o problema a um menor e possibilitando o uso da indução. Fica
fácil ver o porquê da recorrência acima.

Assim programa ficou com complexidade O(s) e encontrou rapidamente a
solução.

Para quem se interessar, o código em linguagem C ficou bem simples e segue
abaixo :
-----------[ inicio ]--------------------------
#include <stdio.h>
#define MAX 10000

int T[MAX+1];

int main() {
  int i;

  T[1]=1;
  printf("T(1) = 1\n");
  for(i=2; i<=MAX; i++) {
    T[i] = T[i-1]==1 ? i : T[i-1]-1;
    printf("T(%d) = %d\n", i, T[i]);
    if(T[i]==2001) break;
  }
  return 0;
}
-------------------[ fim ]-------------

Um abraço

[     Vinicius José Fortuna      ]
[ vinicius.fortuna@ic.unicamp.br ]


On Wed, 1 Jan 1997 ezer@ig.com.br wrote:

> Um que foi enviado para esta lista ha algum tempo pela Fernanda (ola!), foi
> o do baralho - que nao eh explicitamente um problema de computacao, mas
> claramente um problema algoritmico.
> 
> >Olá,gostaria de ajuda nesta questão:
> >
> >Temos um baralho especial de cartas. As cartas são numeradas e estão
> >colocadas por ordem.A nº 1 é a que está por baixo,a nº 2 está por cima da 
> >nº
> >1,e assim sucessivamente.Carta de nº mais alto é a que está por cima.O
> >total de cartas é inferior a 5000.Toma-se a carta superior e coloca-se sob 
> >o
> >baralho.Pega-se na seguinte,q sai fora do jogo.A nova carta superior do
> >baralho é colocada sob o baralho e a seguinte sai fora do jogo.E 
> >continua-se
> >assim até q resta apenas uma carta,que por sinal, tem o nº 2001. Quantas
> >cartas tinha o baralho?
> >Obrigada!
> >Fê
> 
> Nesse momento estou tentando resolve-lo

=========================================================================
Instruções para entrar na lista, sair da lista e usar a lista em
http://www.mat.puc-rio.br/~nicolau/olimp/obm-l.html
O administrador desta lista é <nicolau@mat.puc-rio.br>
=========================================================================