codice:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <set> 
using std::cout;
using std::cin;
using std::dec;
using std::hex;
class Casella{
public:
    enum stato{vuoto=0,pienoA,pienoB};    
     typedef std::set<Casella *> Container;
     typedef Container::iterator Iterator; 
private:
     stato stato_;
     int vicini_futuri;
     int vicini;
     Container osservatori;
public:
     Casella( const Casella::stato& s = Casella::vuoto ) 
      : stato_(s), vicini_futuri(0), vicini(0){}  
    Casella(const Casella& c): vicini(c.vicini),
             vicini_futuri(c.vicini_futuri), stato_(c.stato_){}
     virtual ~Casella(){}  
    inline void Registra(Casella& c) {
         if (&c != this){
                osservatori.insert(&c);
         }
     } 
    inline void Imposta(const Casella::stato& s){
        stato_=s;
     }
      inline void MuoriA(){
       if(stato_==pienoA){
        Imposta(Casella::vuoto);
        Notifica(-1);
       }
     }
      inline void MuoriB(){
       if(stato_==pienoB){
        Imposta(Casella::vuoto);
        Notifica(-1);
       }
     }
    inline void NasciA() {
        if (stato_==vuoto){
         Imposta(Casella::pienoA);
         Notifica(1);
        }
     } 
    inline void NasciB() {
        if (stato_==vuoto){
         Imposta(Casella::pienoB);
         Notifica(1);
        }
     } 
    inline void Ciclo() {
       vicini=vicini_futuri;
     }
    inline void Verifica() {
         if (stato_==pienoB){
            if (vicini<2 || vicini>3) 
               MuoriB();
         }else {
            if (vicini==3) 
               NasciB();
           }
        if (stato_==pienoA){
            if (vicini<1 || vicini>2) 
               MuoriA();
         else {
            if (vicini==2) 
               NasciA();
           }
     } 
     }
    inline bool LeggiA() const{
         return stato_==pienoA;
     }
    inline bool LeggiB() const{
         return stato_==pienoB;
     }
private:
    inline void Notifica(int msg) const{
         for (Iterator it = osservatori.begin(); it != osservatori.end(); ++it){
             (*it)->RiceviNotifica(msg);
         }
     }
    inline void RiceviNotifica(int msg) {
         vicini_futuri += msg;//equivale a vicini_futuri=vicini_futuri + msg
     }
}; 
class Griglia{
public:
     typedef std::vector<Casella> Container;
     typedef Container::iterator Iterator;
private:
     int righe_;
     int colonne_;
     Container griglia;
public:
     virtual ~Griglia(){}
    Griglia(const int& righe, const int& colonne)
      :righe_(righe), colonne_(colonne)    {
       if (righe_ < 5) righe_=5;
       if (colonne_ < 5) righe_=5;
       griglia.reserve(righe_*colonne_);
       griglia.resize(righe_*colonne_);
     }
    inline Casella& operator[](const int n) { //'operator' Returns a reference to the element at position n in the vector container
       return griglia[n];
     }
    inline void Cicla() {    
       for (int i = 0; i < righe_*colonne_;++i)
           griglia[i].Ciclo();
     }
    void Verifica(){
       for (int i = 0; i < righe_*colonne_;++i)
           griglia[i].Verifica();
     }
      inline void ImpostaB (const int& pos) {
         if ((pos >=0)&&(pos < griglia.size()))           
           griglia[pos].NasciB();
     }
      inline void ImpostaA (const int& pos) {
         if ((pos >=0)&&(pos < griglia.size()))           
           griglia[pos].NasciA();
     }
     inline void ResettaA (const int& pos) {
         if ((pos >=0)&&(pos < griglia.size()))   
           griglia[pos].MuoriA();
     }
    inline void ResettaB (const int& pos) {
         if ((pos >=0)&&(pos < griglia.size()))   
           griglia[pos].MuoriB();
     }
    inline void Genera(){
       bool primo, ultimo;
       for (int indice=0; indice< righe_*colonne_;++indice){
         primo = ( (indice%colonne_) == 0);
         ultimo = ( (indice%colonne_) == colonne_-1);
        if (indice > colonne_){      
           if (!primo)
              griglia[indice].Registra(griglia[indice-colonne_ - 1]);
           griglia[indice].Registra(griglia[indice-colonne_]);
           if (!ultimo)
              griglia[indice].Registra(griglia[indice-colonne_ + 1]);
         }
        if (!primo)
           griglia[indice].Registra(griglia[indice-1]);
         if (!ultimo)
           griglia[indice].Registra(griglia[indice+1]);
        if (indice < ((colonne_)*(righe_-1)) ){
           if (!ultimo)
             griglia[indice].Registra(griglia[indice+colonne_+1]);
           griglia[indice].Registra(griglia[indice+colonne_]);      
           if (!primo)
             griglia[indice].Registra(griglia[indice+colonne_-1]);
         } 
       } 
     }
    inline const int Righe() const { return righe_; }
     inline const int Colonne() const { return colonne_; }
};