#include #include #include #define MAX_POM 10 #define MAX_N 30000 #define MAX_M 1000000 #define MAX_DELKA 10 #define MIN(a, b) ((a) < (b) ? (a) : (b)) // graf pomocí seznamu následovníků struct hrana { int V; int delka; struct hrana *dalsi; }; typedef struct hrana hrana; // číslujeme od 1 do MAX_N, proto si vytvoříme pole o jedna větší // a prvky indexované nulou nebudeme používat hrana *G[MAX_N+1]; int pom[MAX_N+1]; // počet pomerančů ve křižovatkách int N, M; // počty vrcholů a hran int S, C; // číslo počátečního a cílového vrcholu // stavový prostor vrcholy × pomeranče, které máme int X[MAX_N][MAX_POM+1]; struct fronta { int V; int pom; struct fronta *dalsi; }; typedef struct fronta fronta; fronta *zac = NULL, *kon = NULL; void fr_pridej(int V, int pom) { fronta *f = malloc(sizeof(fronta)); f->V = V; f->pom = pom; f->dalsi = NULL; if(zac==NULL) { zac = kon = f; } else { kon->dalsi = f; kon = f; } } bool fr_vyjmi(int *V, int *pom) { fronta *f = zac; if(f==NULL) return false; zac = zac->dalsi; if(zac==NULL) kon = NULL; *V = f->V; *pom = f->pom; free(f); return true; } void konec(void); int main(void) { int i, y; // vstup scanf("%d %d %d %d", &N, &M, &S, &C); for(i=1; i<=N; i++) scanf("%d", &pom[i]); for(i=1; i<=N; i++) G[i] = NULL; for(i=0; iV = v2; h1->delka = delka; h1->dalsi = G[v1]; G[v1] = h1; h2->V = v1; h2->delka = delka; h2->dalsi = G[v2]; G[v2] = h2; } for(i=1; i<=N; i++) for(y=0; y<=MAX_POM; y++) X[i][y] = -1; // stav nenavštíven fr_pridej(S, pom[S]); X[S][pom[S]] = 0; // BFS int V, V_pom; while(fr_vyjmi(&V, &V_pom)) { if(V == C) // nalezená cesta { printf("%d\n", X[V][V_pom]); #ifdef DEBUG // zpětný průchod pro nalezení a vypsání cesty printf("Konec ve vrcholu %d\n", V); while(V != S || V_pom != pom[S]) { hrana *h = G[V]; bool nalezeno = false; while(h) { int zpet = h->V, zpet_pom = V_pom - pom[V] + h->delka; if(zpet_pom <= MAX_POM) { if(X[zpet][zpet_pom] == X[V][V_pom] - 1) { printf("Vrchol %d, pomerancu %d\n", zpet, zpet_pom); V = zpet; V_pom = zpet_pom; nalezeno = true; break; } } h = h->dalsi; } assert(nalezeno); } #endif konec(); } // procházíme sousední vrcholy hrana *h = G[V]; while(h) { int cil = h->V, cil_pom = MIN(V_pom - h->delka + pom[cil], MAX_POM); if(h->delka <= V_pom && X[cil][cil_pom]==-1) { X[cil][cil_pom] = X[V][V_pom] + 1; fr_pridej(cil, cil_pom); } h = h->dalsi; } } // cesta nenalezena printf("-1\n"); konec(); } void uvolni(hrana *h) { if(h==NULL) return; uvolni(h->dalsi); free(h); } void konec(void) { int i; // graf for(i=1; i<=N; i++) uvolni(G[i]); // fronta int xxx; while(fr_vyjmi(&xxx, &xxx)); exit(0); }