splitdaoo.cpp

// $Id$
/* COMIENZO DE DESCRIPCION

   __USE_WIKI__
   Dados dos enteros #M# y #n#, tales que #n<M# crear un AOO
   #T# tal que: 1) La suma de las hojas es #M#, pero cada
   una de ellas es #h<=n#. 2) Se satisface que para cada
   nodo #p# la suma de sus hijos es #*p#. 3) Cada nodo tiene
   a lo sumo #g# hijos, con #g>1# una constante dada.
   Ayuda: El arbol se puede construir poniendo inicialmente
   #M# en la raiz, y dividiendo el contenido #*n# de cada
   nodo en #g# valores aprox iguales hasta obtener valores
   #<=n#. [Tomado en el 2do parcial del 2009-10-27].
   keywords: arbol orientado

  FIN DE DESCRIPCION */
// -------------------------------------------------------------------
#include <cstdarg>
#include <cstdio>

#include <iostream>
#include <map>
#include <set>
#include <algorithm>
#include "./util.h"
#include "./tree.h"
#include "./util_tree.h"

using namespace aed;
using namespace std;

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Esta funcion es auxiliar, divide el entero `m'
// en `g' partes menores (g>1) lo mas uniformes posibles.
// Si q = m/g, y r = m%g, entonces a los r primeros
// les toca q+1 y a los restantes q. 
void distrib(int m,int g, vector<int> &v) {
  v.clear();
  // A cada hijo le corresponde q o q+1,
  // dependiendo del resto. 
  int q = m/g, r = m%g, j=0, c;
  for (int j=0; j<g; j++) {
    // Notar que j<r da valores 1 para los r primeros
    // y 0 para el resto
    c = q+(j<r);
    // Solo pone los positivos
    if (c>0) v.push_back(c);
  }
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void split_down(tree<int> &T,node_t p,int n,int g) {
  // Si el valor en la raiz esta OK, entonces no hace falta
  // hacer nada. 
  if (*p <= n) return;
  // Llama a `distrib()' para ver como es la distribucion
  // del valor en el nodo `*p'
  vector<int> v; distrib(*p,g,v);
  // Va iterando, creando los nuevos nodos
  node_t c = p.lchild();
  for (unsigned int j=0; j<v.size(); j++) {
    c = T.insert(c,v[j]);
    // Aplica recursivamente la funcion
    split_down(T,c++,n,g);
  }
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Wrapper
void split_down(tree<int> &T,int M,int n,int g) {
  T.clear();
  T.insert(T.begin(),M);
  split_down(T,T.begin(),n,g);
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int main() {
  tree<int> T;
#define TRY(M,n,g)                              \
  split_down(T,M,n,g);                          \
  printf("M %d, n %d, g %d, T: ",M,n,g);        \
  T.lisp_print(); printf("\n");

  TRY(20,4,3);
  TRY(20,7,3);
  TRY(20,7,2);
  TRY(50,7,4);
  TRY(50,2,4);
  
  return 0;
}

Generated by GNU Enscript 1.6.6.