Clasa a 7-a lecția 7 - 29 oct 2015
From Algopedia
Jump to navigationJump to search
Lectie
Am dat un test de verificare ce continea o problemă care cerea drumul minim într-o matrice. Deplasarea dintr-o căsuța în cealaltă se putea realiza doar pe orizontală sau verticală. Pentru a determina dacă se putea trece dintr-o căsuță în alta trebuiau efectuate operații pe biți. De asemenea, problema cerea și reconstituirea drumului minim în mod recursiv.
Din păcate, cu aproximativ 10 minute înainte de terminarea timpului s-a întrerupt curentul în liceu iar mulți dintre voi nu au apucat să-și trimită sursele la care încă mai lucrau.
Soluțiile oficiale
Panda
#include <stdio.h>
#define MAX_N 500
#define MAX_M 500
struct Tarc {
short int l;
short int c;
};
Tarc aduna(Tarc a, Tarc b) {
Tarc t;
t.l = a.l + b.l;
t.c = a.c + b.c;
return t;
}
Tarc vecini[] = {
{ 0, 1},
{ 0, -1},
{ 1, 0},
{-1, 0},
};
int P;
int N, M, T;
int L, C, K, S;
Tarc sursa;
char areMancare[1 + MAX_N + 1][1 + MAX_M + 1];
char accesibil[1 + MAX_N + 1][1 + MAX_M + 1];
int distanta[1 + MAX_N + 1][1 + MAX_M + 1];
Tarc coada[MAX_N * MAX_M];
int inceput, sfarsit;
Tarc drumMinim[MAX_N * MAX_M];
void reconstituireDrumMinim(Tarc tarc) {
int i;
drumMinim[distanta[tarc.l][tarc.c]] = tarc;
if (distanta[tarc.l][tarc.c] > 1) {
i = -1;
Tarc tarcNou;
do {
i++;
tarcNou = aduna(tarc, vecini[i]);
} while (distanta[tarcNou.l][tarcNou.c] + 1 != distanta[tarc.l][tarc.c]);
reconstituireDrumMinim(tarcNou);
}
}
int main() {
int i, j;
FILE *in = fopen("panda.in", "r");
FILE *out = fopen("panda.out", "w");
// FILE *in = stdin;
// FILE *out = stdout;
fscanf(in, "%d", &P);
fscanf(in, "%d %d %d", &N, &M, &T);
fscanf(in, "%d %d %d %d", &L, &C, &K, &S);
sursa.l = L;
sursa.c = C;
for (i = 0; i < T; i++) {
fscanf(in, "%d %d", &L, &C);
areMancare[L][C] = 1;
}
int accesibile = 0;
for (i = 1; i <= N; i++) {
for (j = 1; j <= M; j++) {
int cod;
fscanf(in, "%d", &cod);
accesibil[i][j] =
(((cod | K) & ((1 << S) - 1)) == ((1 << S) - 1)) &&
(((cod & K) & ((1 << S) - 1)) == 0);
if (!(i == sursa.l && j == sursa.c))
accesibile += accesibil[i][j];
}
}
inceput = sfarsit = 0;
coada[sfarsit] = sursa;
sfarsit++;
distanta[sursa.l][sursa.c] = 1;
while (inceput < sfarsit) {
Tarc tarc = coada[inceput];
inceput++;
for (i = 0; i < 4; i++) {
Tarc tarcNou = aduna(tarc, vecini[i]);
if (accesibil[tarcNou.l][tarcNou.c]) {
if (distanta[tarcNou.l][tarcNou.c] == 0) {
distanta[tarcNou.l][tarcNou.c] = distanta[tarc.l][tarc.c] + 1;
coada[sfarsit] = tarcNou;
sfarsit++;
}
}
}
}
int distantaMinima = 0x7fffffff;
int nrTarcuriMinime = 0;
Tarc tarcMinim;
for (i = 1; i <= N; i++) {
for (j = 1; j <= M; j++) {
if (areMancare[i][j] && distanta[i][j] > 0) {
if (distantaMinima > distanta[i][j]) {
distantaMinima = distanta[i][j];
nrTarcuriMinime = 1;
tarcMinim.l = i;
tarcMinim.c = j;
} else if (distantaMinima == distanta[i][j]) {
nrTarcuriMinime++;
}
}
}
}
distantaMinima--;
//reconstituireDrumMinim(tarcMinim);
if (P == 1) {
fprintf(out, "%d\n", accesibile);
} else if (P == 2) {
fprintf(out, "%d %d\n", distantaMinima, nrTarcuriMinime);
// } else {
// for (i = 1; i <= distantaMinima + 1; i++) {
// fprintf(out, "%d %d\n", drumMinim[i].l, drumMinim[i].c);
// }
}
fclose(in);
fclose(out);
return 0;
}
Pandele
#include <stdio.h>
#define MAX_N 500
#define MAX_M 500
struct Tarc {
int l;
int c;
};
Tarc aduna(Tarc a, Tarc b) {
Tarc t;
t.l = a.l + b.l;
t.c = a.c + b.c;
return t;
}
Tarc vecini[] = {
{ 0, 1},
{ 0, -1},
{ 1, 0},
{-1, 0},
};
int P;
int N, M, T;
int L, C, K, S;
Tarc sursa;
int areMancare[1 + MAX_N + 1][1 + MAX_M + 1];
int accesibil[1 + MAX_N + 1][1 + MAX_M + 1];
int distanta[1 + MAX_N + 1][1 + MAX_M + 1];
Tarc coada[MAX_N * MAX_M];
int inceput, sfarsit;
Tarc drumMinim[MAX_N * MAX_M];
void reconstituireDrumMinim(Tarc tarc) {
int i;
drumMinim[distanta[tarc.l][tarc.c]] = tarc;
if (distanta[tarc.l][tarc.c] > 1) {
i = -1;
Tarc tarcNou;
do {
i++;
tarcNou = aduna(tarc, vecini[i]);
} while (distanta[tarcNou.l][tarcNou.c] + 1 != distanta[tarc.l][tarc.c]);
reconstituireDrumMinim(tarcNou);
}
}
int main() {
int i, j;
FILE *in = fopen("pandele.in", "r");
FILE *out = fopen("pandele.out", "w");
// FILE *in = stdin;
// FILE *out = stdout;
fscanf(in, "%d", &P);
fscanf(in, "%d %d %d", &N, &M, &T);
fscanf(in, "%d %d %d %d", &L, &C, &K, &S);
sursa.l = L;
sursa.c = C;
for (i = 0; i < T; i++) {
fscanf(in, "%d %d", &L, &C);
areMancare[L][C] = 1;
}
int accesibile = 0;
for (i = 1; i <= N; i++) {
for (j = 1; j <= M; j++) {
int cod;
fscanf(in, "%d", &cod);
accesibil[i][j] =
(((cod | K) & ((1 << S) - 1)) == ((1 << S) - 1)) &&
(((cod & K) & ((1 << S) - 1)) == 0);
if (!(i == sursa.l && j == sursa.c))
accesibile += accesibil[i][j];
}
}
inceput = sfarsit = 0;
coada[sfarsit] = sursa;
sfarsit++;
distanta[sursa.l][sursa.c] = 1;
while (inceput < sfarsit) {
Tarc tarc = coada[inceput];
inceput++;
for (i = 0; i < 4; i++) {
Tarc tarcNou = aduna(tarc, vecini[i]);
if (accesibil[tarcNou.l][tarcNou.c]) {
if (distanta[tarcNou.l][tarcNou.c] == 0) {
distanta[tarcNou.l][tarcNou.c] = distanta[tarc.l][tarc.c] + 1;
coada[sfarsit] = tarcNou;
sfarsit++;
}
}
}
}
int distantaMinima = 0x7fffffff;
int nrTarcuriMinime = 0;
Tarc tarcMinim;
for (i = 1; i <= N; i++) {
for (j = 1; j <= M; j++) {
if (areMancare[i][j] && distanta[i][j] > 0) {
if (distantaMinima > distanta[i][j]) {
distantaMinima = distanta[i][j];
nrTarcuriMinime = 1;
tarcMinim.l = i;
tarcMinim.c = j;
} else if (distantaMinima == distanta[i][j]) {
nrTarcuriMinime++;
}
}
}
}
distantaMinima--;
reconstituireDrumMinim(tarcMinim);
// if (P == 1) {
// fprintf(out, "%d\n", accesibile);
// } else if (P == 2) {
// fprintf(out, "%d %d\n", distantaMinima, nrTarcuriMinime);
// } else {
for (i = 1; i <= distantaMinima + 1; i++) {
fprintf(out, "%d %d\n", drumMinim[i].l, drumMinim[i].c);
}
// }
fclose(in);
fclose(out);
return 0;
}
Temă
Pentru data viitoare veți avea de rezolvat ca temă problema dată la test în cele două forme ale sale: