// Řešení 34-5-2 průchodem přes konce událostí // Napsal Martin Medvěd Mareš #include #include #include #include #include #include using namespace std; #define MAXN 1000 // Maximální počet vrcholů #define INFTY 1000000000 // "nekonečno" #if 0 #define DBG(...) printf(__VA_ARGS__) #else #define DBG(...) do { } while (0) #endif // Graf a předpočítané vzdálenosti v něm int N, M; int D[MAXN][MAXN]; // vzdálenosti v grafu int P[MAXN][MAXN]; // předchůdci na nejkratší cestě // Události a příchody do vrcholů int U; struct udalost; struct prichod { // Příchod do vrcholu int kdy; udalost *odkud; bool operator < (const prichod &y) const { return kdy > y.kdy; } }; // Vrchol si pamatuje seznam dosud nepoužitých příchodů setříděný podle času struct vrchol { priority_queue prichody; }; vector vrcholy; struct udalost { int id; int kde; int zacatek, konec; // konec = zacatek + delka int zisk; // maximální zisk, pokud trasa skončí touto událostí udalost *predchozi; // předchozí událost v optimálním řetězci bool operator < (const udalost &y) const { return zacatek < y.zacatek; } }; vector udalosti; udalost *opt_udalost; // událost se zatím maximálním ziskem // Čtení vstupu void nacti_vstup() { scanf("%d%d%d", &N, &M, &U); assert(N > 0 && N <= MAXN); assert(M >= 0); assert(U > 0); vrcholy.resize(N); for (int i=0; i= 0 && x < N); assert(y >= 0 && y < N); assert(x != y); assert(D[x][y] == INFTY); D[x][y] = d; P[x][y] = x; } for (int i=0; i= 0 && u.kde < N); u.id = i; u.konec = u.zacatek + delka; u.zisk = -INFTY; u.predchozi = NULL; udalosti.push_back(u); } } // Výpočet vzdáleností Floydovým-Warshallovým algoritmem void floyd_warshall() { for (int k=0; k\n", u.kde, u.zacatek, u.konec); // Projdeme všechny relevantní příchody while (!v->prichody.empty()) { const prichod &s = v->prichody.top(); if (s.kdy >= u.konec) break; int zisk = s.odkud ? s.odkud->skore : 0; zisk += u.konec - max(u.zacatek, s.kdy); DBG("\t@%d: zisk=%d pred=%d\n", s.kdy, skore, s.odkud ? s.odkud->id : -1); if (zisk > u.skore) { u.zisk = skore; u.predchozi = s.odkud; } v->prichody.pop(); } // Pokud jsme tuto událost mohli navštívit, probereme přesuny z jejího // konce do ostatních vrcholů a vytvoříme vrcholům příchody. DBG("\t== nejlepší=%d, pred=%d\n", u.zisk, u.predchozi ? u.predchozi->id : -1); if (u.zisk > -INFTY) { for (int j=0; j %d @%d\n", j, dalsi.kdy); } if (!opt_udalost || u.zisk > opt_udalost->skore) opt_udalost = &u; } } } // Výpis trasy void vypis() { assert(opt_udalost); printf("%d\n", opt_udalost->zisk); deque cesta; for (udalost *u=opt_udalost; u; u=u->predchozi) cesta.push_front(u); int kde_jsem = 0; int cas = 0; deque presuny; for (auto u: cesta) { if (u->kde != kde_jsem) { presuny.clear(); int i = u->kde; while (i != kde_jsem) { assert(i >= 0); presuny.push_front(i); i = P[kde_jsem][i]; } int d = 0; int ma_byt_d = D[kde_jsem][u->kde]; for (int i: presuny) { printf("P %d\n", i); d += D[kde_jsem][i]; kde_jsem = i; } assert(d == ma_byt_d); cas += d; } printf("C %d\n", u->konec - cas); cas = u->konec; } } int main() { nacti_vstup(); sort(udalosti.begin(), udalosti.end()); floyd_warshall(); simulace(); vypis(); return 0; }