Sums between two values. OpenMP version

We consider a set of N natural numbers, with values Vi, 1<=i<=N, and two numbers C1 and C2. The problem is to obtain the number of subsets of the N numbers whose sum is between C1 and C2. There can be repeated numbers in V.


A number of problems is solved. For each problem the function to parallelize has:

Input parameters:

-int N: number of natural numbers

-int *V: a vector with the values of the numbers

-int C1: the minimum bound for the value for the sums of numbers

-int C2: the maximum bound

Files

3

5 1 4 9 10 15

30 2 4 41 30 1550

29 3 5 65 80 1670

/*
  CPP_CONTEST=2018Qual
  CPP_PROBLEM=D
  CPP_LANG=CPP+OPENMP
  CPP_PROCESSES_PER_NODE=1
  CPP_NUM_NODES=1
*/

#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#include <iostream>
#include <iomanip>    
#include <math.h>

using namespace std;

int back(int N,int *V,bool *obtained,int num,int sum,int C1,int C2)
{
  int numsums=0; //for the number of sums

  for(int i=num+1;i<N;i++) //the number to be included in the set. Only numbers after number i
  {
     if(!obtained[sum+V[i]] and C1<=sum+V[i] and sum+V[i]<=C2) //if the number is in the range
     {
        obtained[sum+V[i]]=true; 
        numsums++;
#ifdef DEBUG
    cout << "obtained with sum: "<<sum<< " and value "<<V[i]<<endl;
#endif
     }
     numsums+=back(N,V,obtained,i,sum+V[i],C1,C2); //the remaining elements are those after number i. Parameters i and V[i] correspond to the number and the accumulated sum 
  }
  return numsums;
}

int  sec(int N,int *V,int C1,int C2)
{
  int numsums=0; //for the total number of sums
  bool *obtained=(bool *) calloc(sizeof(bool),C2); //stores the values obtained as sum of a subset of the natural numbers

  for(int i=0;i<N;i++) //the first number included in the set
  {
     if(!obtained[V[i]] and C1<=V[i] and V[i]<=C2) //if the number is in the range
     {
        obtained[V[i]]=true; 
        numsums++;
#ifdef DEBUG
    cout << "obtained with sum: 0 , and value "<<V[i]<<endl;
#endif
     }
     numsums+=back(N,V,obtained,i,V[i],C1,C2); //the remaining elements are those after number i. Parameters i and V[i] correspond to the number and the accumulated sum 
  }
  free(obtained);
  return numsums;
}
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <omp.h>
#include <signal.h>
#include <unistd.h>
#include <iostream>
#include <iomanip>
#include <math.h>

using namespace std;

// Scheme for the problem of Sums between two values - OpenMP version
// Qualification contest for the Spanish Parallel Programming Contest 2018, problem D

//initialize a vector
void inicialize(int n,int *m,int lv,int uv)
{
    for(int i=0;i<n;i++)
      m[i]=int(((1.*rand())/RAND_MAX)*(uv-lv)+lv);
}

//write a matrix, only for debug
void escribir(int n,int m,int *a){
  for (int i = 0; i < n; i++)
  {
      for(int j=0;j<m;j++)
           cout << a[i*m+j]<<" ";
      cout <<endl; 
 }
  cout <<endl;
}

/*
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;
}

//abort with the maximum execution time is reached
static void alarm_handler(int sig) {
  fprintf(stderr, "Time Limit Exceeded\n");
  abort();
}

//the external function to be parallelized by the contestants
extern int sec(int,int *,int,int);

int main(int argc,char *argv[]) {
  int num_problems; //number of problems  
  int N; //number of natural numbers
  int *V; //values of the numbers
  int seed; //seed for random generation  
  int lower_value;  //lower bound for the values in the vector
  int upper_value;  //upper bound for the values in the vector
  int C1,C2; //interval for the number of sums
  long long ti,tf,tt=0; //initial, final and total times
  FILE *stats_file = fopen("stats", "w");

//to stablish a time limit
  struct sigaction sact;
  sigemptyset(&sact.sa_mask);
  sact.sa_flags = 0;
  sact.sa_handler = alarm_handler;
  sigaction(SIGALRM, &sact, NULL);
  alarm(100);  /* time limit */
 
//  MPI_Init(&argc,&argv);
//  MPI_Comm_size(MPI_COMM_WORLD,&np);
//  MPI_Comm_rank(MPI_COMM_WORLD,&nodo);

// The number of test cases is read
// and sent to all the processes
//  if(nodo==0)
//  {
    cin >> num_problems;
//    MPI_Bcast(&cuantos,1,MPI_INT,0,MPI_COMM_WORLD);
//  }
//  else
//  {
//    MPI_Bcast(&cuantos,1,MPI_INT,0,MPI_COMM_WORLD);
//  }
  for(int i=0;i<num_problems;i++)
  {
//    if(nodo==0)
//    {
      cin >>N;                   // The first argument is the size of the vector
      cin >>seed; //seed for the random generation of data to generate
      cin >>lower_value;  //lower bound for the values in the vector
      cin >>upper_value;  //upper bound for the values in the vector
      cin >> C1 >> C2;
// Space for the data
      V = new int[N];
      inicialize(N,V,lower_value,upper_value);
      

      srand(seed);

#ifdef DEBUG
// While debugging the vector written
      escribir(1,N,V);
#endif


//    }
//    MPI_Barrier(MPI_COMM_WORLD);
    ti=mseconds(); 
    int result=sec(N,V,C1,C2);
//    MPI_Barrier(MPI_COMM_WORLD);
    tf=mseconds(); 
//    if(nodo==0)
//    {
// The time of the first input is not considered
      if(i!=0) tt+=tf-ti;
#ifdef DEBUG
// While debugging the time of each execution is written
      fprintf(stats_file, "%Ld\n", tf-ti);
#endif
// The results of each problem are written,
// even for the first problem
      cout <<result<<endl;
      delete[] V;
//    } */
  }
  

//  if(nodo==0)
//  { 
    fprintf(stats_file, "%Ld\n", tt);
    fclose(stats_file);
//  }
//  MPI_Finalize();
  return 0;
}