tpl320171102.cpp

#define USECHRONO
#include "eval.hpp"
#include <cassert>
#include <climits>
#include <cstdlib>
#include <stack>
#include <map>

using namespace aed;
using namespace std;

/* COMIENZO DE DESCRIPCION

   __USE_WIKI__

   #isBST:# Dado un arbol binario #T,# determinar si es un
    arbol binario de busqueda.

    #fillBST:# Dada una lista de enteros #L# y un arbol
    binario #T,# generar #fillBST# que inserta los elementos
    de #L# en #T# formando un arbol binario de busqueda
    siguiendo el orden original de #L.#

    #eqsumplit.# Escribir un predicado que retorna #true#
    sii el conjunto #S# se puede descomponer en dos conjuntos
    disjuntos #S1# y #S2# tales que la suma de los elementos
    de #S1# es igual a la suma de #S2.#

    [Tomado en el TPL3 de 2017-11-02].  
    keywords: arbol binario, conjunto

FIN DE DESCRIPCION */

void inorden(btree<int>&T,btree<int>::iterator it,list<int>&L){
  // Genera el listado en orden simetrico
  if(it == T.end())
    return;
  inorden(T,it.left(),L);
  L.push_back(*it);
  inorden(T,it.right(),L);
}

// Un arbol binario AB es de busqueda sii el listado en
// orden simetrico esta ordenado.
bool isBST(btree<int>&T){
  list<int> orden;
  inorden(T,T.begin(),orden);
  list<int>::iterator it, it2;
  it = orden.begin();
  it2 = it;it2++;
  while(it2!=orden.end()){
    // Chequea que los elementos esten ordenados y sean
    // estrictamente diferentes.
    if(*it2<=*it)
      return false;
    it++;it2++;
  }
  return true;
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Otra solucion. La funcion recursiva retorna si
// ademas el minimo y el maximo del subarbol
bool isBST2(btree<int>&T, btree<int>::iterator it,
            int &min,int &max){
  if (it==T.end()) {
    // INT_MAX, INT_MIN estan definidos en `climits.h'
    min = INT_MAX;
    max = INT_MIN;
    return true;
  }
  int minr,maxr,minl,maxl;
  auto ql=it.left(), qr=it.right();
  if (!isBST2(T,ql,minl,maxl)) return false;
  if (!isBST2(T,qr,minr,maxr)) return false;
  int n = *it;
  if (maxl>=n || minr<=n) return false;
  min = (ql==T.end()? n : minl);
  max = (qr==T.end()? n : maxr);
  return true;
}

bool isBST2(btree<int>&T){
  int min,max;
  return isBST2(T,T.begin(),min,max);
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Otra solucion. Usa funciones auxiliares para el minimo
// y maximo de un BT.

// Busca el minimo avanzando por hijo izquierdo
int min(btree<int>&T, btree<int>::iterator n) {
  if (n==T.end()) return INT_MAX;
  auto c=n;
  while (1) {
    c = n.left();
    if (c==T.end()) return *n;
    n=c;
  }
}

// Busca el maximo avanzando por hijo derecho
int max(btree<int>&T, btree<int>::iterator n) {
  // INT_MAX, INT_MIN estan definidos en `climits.h'
  if (n==T.end()) return INT_MIN;
  auto c=n;
  while (1) {
    c = n.right();
    if (c==T.end()) return *n;
    n=c;
  }
}

bool isBST3(btree<int>&T, btree<int>::iterator n){
  // Un arbol vacio es BST
  if (n==T.end()) return true;
  auto ql=n.left(), qr=n.right();
  // Chequea que los subarboles der e izq sean BST
  if (!isBST3(T,ql)) return false;
  if (!isBST3(T,qr)) return false;
  // Chequea la condicion en el nodo
  return max(T,ql)<*n && *n<min(T,qr);
}

bool isBST3(btree<int>&T){ return isBST3(T,T.begin()); }

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
void fillBST(btree<int>&T,list<int>&L){
  btree<int>::iterator n = T.begin();
  if(L.empty()) return;
  n = T.insert(n,*L.begin());
  L.erase(L.begin());
  while(!L.empty()){
    while(n != T.end()){
      if(*n>*L.begin())
        n = n.left();
      else if(*n<*L.begin())
        n = n.right();
      else {
        if(L.size() != 1)
          n = T.begin();
        else n = T.end();
        L.erase(L.begin());
      }
    }
    if(L.size()>=1 && n !=T.begin()){
      n = T.insert(n,*L.begin());
      L.erase(L.begin());
      n = T.begin();
    }
  }
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Basicamente es un algoritmo tipo
// powerset es decir prueba con S1 todos los subconjuntos de
// S. Para cada S1 

// Funcion auxiliar calcula la suma de los elementos de un conjunto
int sum(set<int> &S) {
  int s=0;
  for (auto q:S) s+=q;
  return s;
}

// Funcion recursiva auxiliar. Chequea con todos los S1
// subconjuntos de W.
bool eqsumsplit(set<int> &S,set<int> &W) {
  // Prueba con S1=W
  set<int> S2,S1=W;
  set_difference(S,S1,S2);
  if (sum(S1)==sum(S2)) return true;
  // Prueba recursivamente con todos los subconjuntos
  // que se obtienen tomando cualquier elemento `x' de
  // W y formando W-{x}
  for (auto x:W) {
    set<int> W1=W;
    W1.erase(x);
    if (eqsumsplit(S,W1)) return true;
  }
  // No encontro ninguna solucion
  return false;
}

// Wrapper que llama a la recursiva
bool eqsumsplit(set<int> &S) {
  return eqsumsplit(S,S);
}

//---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
// Otra solucion.
bool eqssplit2(set<int> &SS, int s1=0, int s2=0) {
  set<int> S=SS;
  if (S.empty()) return s1==s2;
  int x = *S.begin(); S.erase(S.begin());
  if (eqssplit2(S,s1+x,s2)) return true;
  if (eqssplit2(S,s1,s2+x)) return true;
  return false;
}

// Wrapper
bool eqsumsplit2(set<int> &SS) { return eqssplit2(SS); }

  //---:---<*>---:---<*>---:---<*>---:---<*>---:---<*>
int main() {
  Eval ev;
  int vrbs = 0;
  int seed = 386;
  int h1=0,h2=0,h3=0;

  do {
    ev.eval<1>(isBST,vrbs);
    h1 = ev.evalr<1>(isBST,seed,vrbs);
    
    ev.eval<2>(fillBST,vrbs);
    h2 = ev.evalr<2>(fillBST,seed,vrbs);
    
    ev.eval<3>(eqsumsplit,vrbs);
    h3 = ev.evalr<3>(eqsumsplit,seed,vrbs);
    
    printf("S=%03d -> H1=%03d H2=%03d H3=%03d\n",
           seed,h1,h2,h3);
    
    printf("\n\nIngrese un valor para la semilla:");
  } while (cin>>seed);
  
  return 0;
}

Generated by GNU Enscript 1.6.6.