Dada una matriz de caracteres, A, de dimensión NxN, se obtiene otra matriz de enteros, D, de las mismas dimensiones.
En cada posición (i,j) de D se almacena la menor distancia en A entre la posición (i,j) y otra posición con el mismo carácter A[i,j].
La distancia entre dos posiciones (x1,y1) y (x2,y2) es la distancia de Manhatan: |x2-x1|+|y2-y1|.
Cuando no hay otra posición con el mismo valor se almacena el valor cero.
Finalmente se suman todos los valores almacenados en D.
Por ejemplo, dada la matriz
aabc
cbab
bcca
accb
las distancias son
1 1 2 3
2 2 2 2
2 1 1 2
3 1 1 2
y el resultado es 28.
Se resuelven varios problemas. Para cada problema la función a paralelizar tiene parámetros:
Input parameter:
-int N: número de filas y columnas
-char *A: matriz de caracteres, de dimensión NxN
Return:
int suma de los valores almacenados en D y calculados como se ha indicado
La entrada tiene en la primera línea el número de problemas. Para cada problema hay una línea con tres valores: N, la semilla para la generación aleatoria, número de caracteres distintos a incluir en el array.
3 10 1 8 5900 3 35 5500 5 37
/* CPP_CONTEST=2019Enero CPP_PROBLEM=A CPP_LANG=CPP+OPENMP CPP_PROCESSES_PER_NODE=calisto 1 */ #include < stdio.h > #include < stdlib.h > #include < omp.h > extern void escribir(char *,int,int); void distancia(int n,int row,int column, char *A,int *D) { int distancia=0; //guarda la distancia, si no lo encuentra es 0 int paso=1; //indica el paso por el que vamos int encontrado=0; //indica si se ha encontrado char elemento=A[row*n+column]; //elemento con el que vamos a comparar int rowact,columnizq,columnder; //en cada paso: fila actual, columnas a izquierda y derecha de la que vamos while(!encontrado && paso!=(2*n-1)) //hay un numero maximo de pasos. Si se encuentra se sale { for(rowact=row-paso,columnizq=column,columnder=column;!encontrado && rowact <= row;rowact++,columnizq--,columnder++) //el paso indica cuantas filas por arriba, la primera vez estamos en la misma columna, tanto a izquierda como a derecha //si se encuentra se acaba, o si se llega a la fila actual //se va bajando de fila y la columna izquierda se hace una a la izquierda y la derecha una a la derecha { if((rowact >= 0) && ((columnizq >= 0 && elemento==A[rowact*n+columnizq]) || (columnder < n && elemento==A[rowact*n+columnder]))) //si no nos salimos de la matriz por arriba y //no se sale la columna izquierda y coincide con el elemento, o no se sale la columna derecha y coincide con el elemento { encontrado=1; distancia=paso; } } for(rowact=row+1,columnizq=column-paso+1,columnder=column+paso-1;!encontrado && rowact<=row+paso;rowact++,columnizq++,columnder--) //se empieza en la fila de abajo, la primera vez estamos paso-1 columnas mas a la izquierda y a la derecha //si se encuentra se acaba, o si se llega a la fila actual mas el paso por el que vamos //se va bajando de fila y la columna izquierda se hace una a la derecha y la derecha una a la izquierda { if((rowact < n) && ((columnizq >= 0 && elemento==A[rowact*n+columnizq]) || (columnder < n && elemento==A[rowact*n+columnder]))) { encontrado=1; distancia=paso; } } paso++; } D[row*n+column]=distancia; } void escribirint(int *m, int N,int M) { //solo para DEBUG int i, j; for (i = 0; i < N; i++) { for (j = 0; j < M; j++) printf("%d ", m[i * M + j]); printf("\n"); } printf("\n"); } int sumar(int n,int *m) //suma todos los elementos del array { int s=0; for(int i=0;i < n;i++) s+=m[i]; return s; } int sec(int n,char *A) { int *D=(int*) calloc(sizeof(int),n*n); int result; for (int i = 0; i < n; i++) { for(int j=0;j < n;j++) { distancia(n,i,j,A,D); //calcula la distancia para cada elemento } } #ifdef DEBUG escribirint(D,n,n); #endif result=sumar(n*n,D); delete[] D; return result; }
esquema-openmp.cpp (no modificable, lo usa mooshak para entrada/salida y evaluación, se proporciona para experimentación en local)
#include < stdlib.h > #include < stdio.h > #include < sys/time.h > #include < omp.h > #include < signal.h > #include < unistd.h > //Prueba de Metodología de la Programación Paralela //enero 2019 //Conteo de distancias a elementos iguales en una matriz //Esquema para entrada/salida, validación y toma de tiempos void generar(char *m, int t,int numcar) { int i; for (i = 0; i < t; i++) { m[i] =(char) ((int) (((1. * rand()) / RAND_MAX)*numcar)+'a'); } } void escribir(char *m, int N,int M) { int i, j; for (i = 0; i < N; i++) { for (j = 0; j < M; j++) printf("%c", m[i * M + j]); printf("\n"); } printf("\n"); } /* c c mseconds - returns elapsed milliseconds since Jan 1st, 1970. c */ long long mseconds(){ struct timeval t; gettimeofday(&t, NULL); return t.tv_sec*1000 + t.tv_usec/1000; } static void alarm_handler(int sig) { fprintf(stderr, "Time Limit Exceeded\n"); abort(); } extern int sec(int n,char *A); int main(int argc,char *argv[]) { int N; //tamaño matriz char *A; int cuantos; //número de problemas int semilla; //semilla para generación aleatoria int numcar; //número de caracteres distintos a generar long long ti,tf,tt=0; FILE *stats_file = fopen("stats", "w"); struct sigaction sact; sigemptyset(&sact.sa_mask); sact.sa_flags = 0; sact.sa_handler = alarm_handler; sigaction(SIGALRM, &sact, NULL); alarm(20); /* time limit */ scanf("%d",&cuantos); for(int i=0;i < cuantos;i++) { scanf("%d",&N); scanf("%d",&semilla); scanf("%d",νmcar); A = (char *) calloc(sizeof(char),N*N); srand(semilla); generar(A,N*N,numcar); #ifdef DEBUG escribir(A,N,N); #endif ti=mseconds(); printf("%d\n",sec(N,A)); tf=mseconds(); if(i!=0) tt+=tf-ti; free(A); } fprintf(stats_file, "%Ld\n", tt); fclose(stats_file); return 0; }