Projeto 3 - Uber pool - versão 2

1 Como escolher caronas.

Vamos assumir que 2 passageiros do UBER aceitam dividir a viagem - carona.

Passageiro 1 quer ir de A para B e o passageiro 2 quer ir de C para D.

Então há varias alternativas assumido que eles vão dividir a viagem:

  • pega passageiro 1 em A, pega o 2 em C, deixa 1 em B e deixa 2 em D
  • de A para C para D para B
  • de C para A, para D, para B
  • e de C para A, para B, para D

Se T(A,B) é o tempo de viagem de A para B, e se T(A,C,B) é o tempo de viagem de A para C para B, então a inconveniência para um passageiro por estar dividindo a viagem é a razão do tempo da viagem com carona pelo tempo da viagem sem carona.

Para o primeiro caso, a inconveniência para o passageiro 1 é T(A,C,B)/T(A,B). Para o passageiro 2 a inconveniência é T(C,B,D)/T(C,D).

No segundo caso, a inconveniência para 1 é T(A,C,D,B)/T(A,B), e para o passageiro 2, T(C,D)/T(C,D) = 1.

A uber ira escolher o percurso da carona de tal forma que a maior inconveniência para os 2 passageiros seja a menor possível (ou seja a uber minimiza o máximo da inconveniência para os 2 passageiros). A uber também definiu que a inconveniência máxima para um passageiro é 1.4, ou seja, usando a carona, nunca voce terá um acréscimo maior que 40% no tempo de viagem.

Assim, se nenhum dos percursos acima tiver uma inconveniência maxima para os 2 passageiros menor que 1.4 então não será feito a viagem dividida e cada passageiro fará uma viagem individual.

1.1 exemplo

T(A,B) 40
T(C,D) 15
T(A,C) 5
T(A,D) 10
T(C,A) 8
T(C,B) 40
T(D,B) 35
T(B,D) 30
  • percurso A,C,D,B, incov1 = 5+15+35/40 = 1.375, incov2 = 15/15 = 1
  • percurso A,C,B,D, incov1 = 5+40/40 = 1.125, incov2 = 40+30/15 = 4.66
  • percurso C,A,D,B, incov1 = 10+35/40 = 1.125, incov2 = 8+10/15 = 1.2
  • percurso C,A,B,D, incov1 = 1 , incov2 = 8+40+30/15 = 5.2

A inconveniencia máxima do percurso 1 é 1.375, a do 2 é 4.66, a do 3 é 1.2 e a do 4 é 5.2.

O percurso 2 e 4 não vão ser aceitos pois a inconveniencia máxima é maior que 1.4. Entre os percursos 1 e 3, o sistema escolherá o percurso 2, pois ele tem a menor inconveniencia maxima.

1.2 Viagens em andamento

Pode acontecer que um passageiro ja esta em viagem. Digamos que passageiro A esta indo para B mas a viagem ja esta em andamento, e ele esta em X no momento. O outro passageiro quer ir de de C para D não esta em viagem. Assim se houver uma viagem dividida, ela ja começou em A, (esta agora em X) e portanto os únicos 2 percursos possíveis são A,X,C,B,D ou A,X,C,D,B. A inconveniencia para o passageiro 2 é calculada normalmente. Para o passageiro 1 a inconveniencia deve ser calculada usando o tempo restante da viagem e não o tempo total. Assim a inconveniencia do passageiro 1 para o primeiro percurso é T(X,C,B,D)/T(X,D) e para o outro T(X,C,D)/T(X,D)

2 Projeto

O program lera do standard input dados no formato

0 1 45.6
1 0 44.1
1 2 34.2
2 1 50.1
...

0 10
20 45
30 20 12
50 35 
17 34 23

As primeiras linhas informam o tempo de percurso entre vértices de um grafo. Os vértices são inteiros, 0,1, etc. O grafo é direcionado.

Uma linha vazia separa o segundo bloco de informação, que são as requisições de viagens e as viagens em andamento.

0 10 indica um requisição de viagem, que um passageiro quer ir do vertice 0 a 10. Esse passageiro sera denominado passageiro 1.

20 45 sera a requisição do passageiros 2.

30 28 12 indica uma viagem em andamento, que saiu do vertice 30 para o vertice 28 e se encontra agora no vertice 12.

2.1 Algoritmos

Voce pode usar o Dijkstra para calcular os T(X,Y) das formulas.

Ou voce pode usar o Floyd–Warshall algorithm para calcular de uma vez só os tempos mínimos entre todos os vértices. Uma ideia talvez interessante é implementar o Floyd-Warshall usando operações em matrizes.

Mas considere o caso onde pode haver 2 nos para os quais nao ha um caminho entre eles. Obviamente isso nao acontece numa cidade, mas para testar o programa podemos pensar em um grafo com subgrafos desconexos.

2.2 Saída

A saída deve ser uma lista dos percursos propostos. No máximo 2 passageiros farão uma viagem compartilhada, e assuma uma estratégia gulosa. Escolha o par de passageiros cuja percurso gera o menor inconveniencia maxima, depois o próximo par de passageiros, e assim por diante.

A saida deve ser no seguinte formato

passageiros 3 e 2 percurso: 12 20 45 28
passageiros 1 e 4 percurso: 0 50 35 10
passageiro 5 percurso: 23 34

que indicam que os passageiros 3 e 2 faro uma viajem compartilhada. O percurso (que indica apenas os nos iniciais e finais) começa no 34 onde ou o uber pega o passageiro 3 ou ele ja esta numa viajem em andamento, passa pelo no 12 para pegar o passageiro 2. O resto do percurso indica que a viajem vai ate o no 45 onde um dos passageiros desce e finalmente ate o 8 onde o outro desce.

A segunda linha da saida indica que 1 e 4 nessa ordem, fazem uma viajem compartilhada, e finalmente a ultima linha indica que o passageiro 5 faz a viajem sozinho.

2.3 Execucao

O programa sera rodado com a chamada

python proj3.py entrada1.txt

ou seja o nome do arquivo com a entrada sera parte da chamada (não usarei o standard input como nos outros 2 porjetos). Assim o seu programa deve acessar a linha de execução para sys.argv para descobrir o nome do arquivo de dados.

Se voce esta usando uma bibloteca nao padrao (como o numpy ou outras) avise-o no email de submissao.

Author: Jacques

Created: 2018-11-20 Tue 12:11

Validate