Sobre una matriz de números enteros positivos, $A$ de dimensión NxN, se quiere obtener el camino de longitud máxima desde la primera a la última fila de la matriz. Los posibles caminos empiezan en cualquier elemento de la primera fila, y desde una casilla se avanza a una vecina en la fila siguiente, en la misma columna o en la columna anterior o siguiente. La longitud de un camino viene dada por la suma de los valores en las casillas por las que pasa.
Se resuelven varios problemas. Para cada problema la función a paralelizar devuelve la longitud de camino máximo, y tiene parámetros:
Input parameter:
int N: número de filas y columnas
double *A: matriz de dimensión NxN
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, el valor máximo para la generación (el mínimo es uno).
4 5 6 5 17 11 10 17 12 13 17 1 20
/* CPP_CONTEST=2018Junio CPP_PROBLEM=F CPP_LANG=CPP+OPENMP CPP_PROCESSES_PER_NODE=calisto 1 */ #include <stdlib.h> #include <stdio.h> #include <omp.h> extern void escribir(int *,int,int); void copiar(int n,int *vd,int *vo) //se copia el vector vo en el vd { int i; for(i=0;i<n;i++) vd[i]=vo[i]; } int back(int n,int *A,int fila,int columna) { int valor; if(fila==n-1) return A[fila*n+columna]; else { int maximo=0; if(columna!=0) { valor=A[fila*n+columna]+back(n,A,fila+1,columna-1); if(valor>maximo) maximo=valor; } if(columna!=n-1) { valor=A[fila*n+columna]+back(n,A,fila+1,columna+1); if(valor>maximo) maximo=valor; } valor=A[fila*n+columna]+back(n,A,fila+1,columna); if(valor>maximo) maximo=valor; return maximo; } } int sec(int n,int *A) { int VOA=0; //valor óptimo actual for(int i=0;i<n;i++) //se calculan los óptimos empezando en cada una de las columnas de la primera fila { int valor=0; //para almacenar el valor calculado valor=back(n,A,0,i); //se pasa la fila y columna por lo que se sigue haciendo el backtracking if(valor>VOA) { VOA=valor; } #ifdef DEBUG printf("columna %d , valor %d , optimo %d\n",i,valor,VOA); #endif } return VOA; }
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> #include <iostream> using namespace std; //Prueba de Metodología de la Programación Paralela //junio 2018 //Camino máximo de primera a última fila. Versión OpenMP //Esquema para entrada/salida, validación y toma de tiempos void generar(int *m, int t,int uv) { int i; for (i = 0; i < t; i++) { m[i] =(int) ((1. * rand() / RAND_MAX)*(uv-1)+1); } } void escribir(int *m, int N,int M) { 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"); } /* 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,int *A); int main(int argc,char *argv[]) { int N; //tamaño matriz int *A; int cuantos; //número de problemas int semilla; //semilla para generación aleatoria int uv; //valore superior para generación aleatoria 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(60); /* time limit */ scanf("%d",&cuantos); for(int i=0;i<cuantos;i++) { scanf("%d",&N); scanf("%d",&semilla); scanf("%d",&uv); A = (int *) calloc(sizeof(int),N*N); srand(semilla); generar(A,N*N,uv); #ifdef DEBUG escribir(A,N,N); #endif ti=mseconds(); cout <<sec(N,A)<<endl; tf=mseconds(); #ifdef DEBUG escribir(A,N,N); #endif if(i!=0) tt+=tf-ti; free(A); } fprintf(stats_file, "%Ld\n", tt); fclose(stats_file); return 0; }