Cod sursa(job #3229219)

Utilizator IordachescuVladAlexandruIordachescu Vlad-Alexandru IordachescuVladAlexandru Data 14 mai 2024 16:35:52
Problema Problema rucsacului Scor 0
Compilator c-64 Status done
Runda Arhiva educationala Marime 4.22 kb
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define FILE_IN "rucsac.in"
#define FILE_OUT "rucsac.out"

// Problema rucsacului de pe infoarena

// A doua incercare: merg dupa indicatii

typedef struct
{
  uint16_t w, p;
} ITEM;

int ordine ( const void *e1, const void *e2 )
{
  ITEM *i1 = ( ITEM * ) e1;
  ITEM *i2 = ( ITEM * ) e2;
  if ( i2->w != i1->w )
    return i2->w - i1->w;
  return i2->p - i1->p;
}

uint64_t rezolvare ( uint16_t n, uint16_t g, ITEM *arr )
{
  uint64_t rez = 0;

  uint64_t dp[2][g + 1]; // vectorul de DP pt greutati
  for ( uint16_t i = 0; i <= g; i++ )
    dp[0][i] = 0;

  /*
  for ( uint16_t i = 0; i <= g; i++ )
    {
      printf ( "%2hu ", i );
    }
  printf ( "\n" );
  for ( uint16_t i = 0; i <= g; i++ )
    {
      printf ( "%2lu ", dp[i] );
    }
  printf ( "\n\n" );
  */

  for ( uint16_t j = 0; j < n; j++ )
    {
      for ( int16_t i = g; i >= 0; i-- ) // daca e tot uint, risc overflow
	{
	  if ( dp[j % 2][i] < dp[j % 2][i - arr[j].w] + arr[j].p )
	    {
	      dp[(j + 1) % 2][i] = dp[j%2][i - arr[j].w] + arr[j].p;
	    }
	}
    }

  /*
  for ( uint16_t i = 0; i <= g; i++ )
    {
      printf ( "%2hu ", i );
    }
  printf ( "\n" );
  for ( uint16_t i = 0; i <= g; i++ )
    {
      printf ( "%2lu ", dp[i] );
    }
  */

  rez = dp[(n - 1) % 2][g];
  
  return rez;
}

int main ( void )
{
  FILE *fin, *fout;
  fin = fopen ( FILE_IN, "r" ); fout = fopen ( FILE_OUT, "w" );

  if ( fin == NULL || fout == NULL )
    {
      perror ( "Eroare la deschidere fisiere\n" );
      exit ( -1 );
    }

  
  uint16_t n, g;
  fscanf ( fin, "%hu %hu", &n, &g );

  ITEM arr[n];

  for ( uint16_t i = 0; i < n; i++ )
    {
      fscanf ( fin, "%hu %hu\n", &arr[i].w, &arr[i].p );
      if ( arr[i].w > g )
	{
	  i--, n--;
	  printf ( "Un element > G\n" );
	}
    }

  qsort ( arr, n, sizeof ( ITEM ), ordine ); // preordonarea

  uint64_t rez = rezolvare ( n, g, arr ); // rezolvarea propriu-zisa

  fprintf ( fout, "%lu\n", rez );
  printf ( "%lu\n", rez );

  
  for ( uint16_t i = 0; i < n; i++ )
    {
      printf ( "%2hu %2hu || %2lf\n", arr[i].w, arr[i].p, arr[i].p / ( double ) arr[i].w );
    }
  

  
  if ( ( fclose ( fin ) ) != 0 || ( fclose ( fout ) ) != 0 )
    {
      perror ( "Eroare la inchidere fisiere\n" );
      exit ( -2 );
    }
  
  return 0;
}


// FAIL

// da rezultat gresit, dar aproximativ. In schimb, cel putin pe teste, este foarte rapid

/*
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#define FILE_IN "rucsac.in"
#define FILE_OUT "rucsac.out"

// Problema rucsacului de pe infoarena

// Prima incercare: ordonez obiectele dupa eficienta ( p / w ) si le adaug apoi

typedef struct
{
  uint16_t w, p;
} ITEM;

int ordine ( const void *e1, const void *e2 )
{
  ITEM *i1 = ( ITEM * ) e1;
  ITEM *i2 = ( ITEM * ) e2;
  double r1 = i1->p / ( double ) i1->w, r2 = i2->p / ( double ) i2->w; // rapoartele de eficienta
  if ( r1 != r2 )
    {
      if ( r1 < r2 )
	return 1;
      return -1;
    }
  return i2->w - i1->w;
}

uint64_t rezolvare ( uint16_t n, uint16_t g, ITEM *arr )
{
  uint64_t rez = 0, act_g = 0;

  for ( uint16_t i = 0; i < n; i++ )
    {
      if ( act_g + arr[i].w <= g )
	{
	  rez += arr[i].p;
	  act_g += arr[i].w;
	  printf ( "Am selectat elem || %hu | %hu\n", arr[i].w, arr[i].p );
	}
    }
  
  return rez;
}

int main ( void )
{
  FILE *fin, *fout;
  fin = fopen ( FILE_IN, "r" ); fout = fopen ( FILE_OUT, "w" );

  if ( fin == NULL || fout == NULL )
    {
      perror ( "Eroare la deschidere fisiere\n" );
      exit ( -1 );
    }

  
  uint16_t n, g;
  fscanf ( fin, "%hu %hu", &n, &g );

  ITEM arr[n];

  for ( uint16_t i = 0; i < n; i++ )
    {
      fscanf ( fin, "%hu %hu\n", &arr[i].w, &arr[i].p );
      if ( arr[i].w > g )
	{
	  i--, n--;
	  printf ( "Un element > G\n" );
	}
    }

  qsort ( arr, n, sizeof ( ITEM ), ordine ); // preordonarea

  uint64_t rez = rezolvare ( n, g, arr ); // rezolvarea propriu-zisa

  fprintf ( fout, "%lu\n", rez );
  printf ( "%lu\n", rez );

  
  for ( uint16_t i = 0; i < n; i++ )
    {
      printf ( "%2hu %2hu || %2lf\n", arr[i].w, arr[i].p, arr[i].p / ( double ) arr[i].w );
    }
  

  
  if ( ( fclose ( fin ) ) != 0 || ( fclose ( fout ) ) != 0 )
    {
      perror ( "Eroare la inchidere fisiere\n" );
      exit ( -2 );
    }
  
  return 0;
}
 */