Posiadam sieć stacji w systemie metra. Liczba stacji, liczba biletów, które mogę podróżować pomiędzy stacjami i stacjami, które są ze sobą połączone, są podane w pliku tekstowym jako dane wejściowe do programu. Które stacje są ze sobą połączone są przechowywane w macierzy binarnej 2D. Muszę znaleźć liczbę ścieżek od stacji 0 i z powrotem do 0, która wykorzystuje wszystkie bilety.Programowanie dynamiczne - Zliczanie ścieżek w systemie metra
Oto jeden z przykładów:
W tym przykładzie, istnieje 7 stacji i 5 biletów. Uruchamianie i powrocie do 0, to jest 6 ścieżki:
0-1-2-3-4-0
0-1-5-3-4-0
0-1-6-3-4-0
0-4-3-6-1-0
0-4-3-5-1-0
0-4-3-2-1-0
mają obecnie rekursywne rozwiązanie do tego, że biegnie w O (N^k) (n oznacza liczbę stacji, a k jest liczbą biletów), ale muszę go przekonwertować na iteracyjne, dynamiczne rozwiązanie programistyczne w O (k * N^2), które działa na dowolnym wejściu.
#include <algorithm>
#include <fstream>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
// We will represent our subway as a graph using
// an adjacency matrix to indicate which stations are
// adjacent to which other stations.
struct Subway {
bool** connected;
int nStations;
Subway (int N);
private:
// No copying allowed
Subway (const Subway&) {}
void operator= (const Subway&) {}
};
Subway::Subway(int N)
{
nStations = N;
connected = new bool*[N];
for (int i = 0; i < N; ++i)
{
connected[i] = new bool[N];
fill_n (connected[i], N, false);
}
}
unsigned long long int callCounter = 0;
void report (int dest, int k)
{
++callCounter;
// Uncomment the following statement if you want to get a feel
// for how many times the same subproblems get revisited
// during the recursive solution.
cerr << callCounter << ": (" << dest << "," << k << ")" << endl;
}
/**
* Count the number of ways we can go from station 0 to station destination
* traversing exactly nSteps edges.
*/
unsigned long long int tripCounter (const Subway& subway, int destination, int nSteps)
{
report (destination, nSteps);
if (nSteps == 1)
{
// Base case: We can do this in 1 step if destination is
// directly connected to 0.
if (subway.connected[0][destination]){
return 1;
}
else{
return 0;
}
}
else
{
// General case: We can get to destinaiton in nSteps steps if
// we can get to station S in (nSteps-1) steps and if S connects
// to destination.
unsigned long long int totalTrips = 0;
for (int S = 0; S < subway.nStations; ++S)
{
if (subway.connected[S][destination])
{
// Recursive call
totalTrips += tripCounter (subway, S, nSteps-1);
}
}
return totalTrips;
}
}
// Read the subway description and
// print the number of possible trips.
void solve (istream& input)
{
int N, k;
input >> N >> k;
Subway subway(N);
int station1, station2;
while (input >> station1)
{
input >> station2;
subway.connected[station1][station2] = true;
subway.connected[station2][station1] = true;
}
cout << tripCounter(subway, 0, k) << endl;
// For illustrative/debugging purposes
cerr << "Recursive calls: " << callCounter << endl;
}
int main (int argc, char** argv)
{
if (argc > 1)
{
ifstream in (argv[1]);
solve (in);
}
else
{
solve (cin);
}
return 0;
}
Nie szukam rozwiązania. Obecnie nie mam pomysłów i mam nadzieję, że ktoś wskaże mi właściwy kierunek. Ponieważ muszę wdrożyć do tego podejście oddolne, jak powinienem zacząć od opracowania tabeli programowania dynamicznego z wykorzystaniem najmniejszych pod-problemów?
Czy wymagane jest użycie DP? I znajdziesz wszystkie takie ścieżki? –