ecco a voi il codice per intero
codice:
#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <limits.h>
typedef unsigned int unint;

#define CEILING(X) (X-(int)(X)) > 0 ? (int)(X+1) : (int)(X)

void toggle_db (int, int, int, int , int, unint *****);

int main ()
{
	unint *board2d, *board1d, *****db;
	int NR,NC, i, j, interi ,elem, count,config, cella, num_con, caso;
	int start_cell;
	float integer;
		
	printf("Inserire il numero NR di righe della scacchiera: ");
	scanf("%d", &NR);
	printf("Inserire il numero NC di colonne della scacchiera: ");
	scanf("%d", &NC);
	
	/** Allocazione della scacchiera a due dimensioni **/
	board2d=malloc(NR*NC*sizeof(unint));
	if(board2d==NULL)
	{	
		printf("Spazio non disponibile\n\n");
		return(1);
	}
	
	/** Calcolo dei bit da allocare sottoforma di interi **/
	integer= (float)(NR*NC)/(CHAR_BIT*(sizeof(unint)));
	interi=CEILING(integer);
	
	/** Allocazione della scacchiera rappresentata in una dimensione **/
	
	board1d=malloc(interi*sizeof(unint));
	if(board1d==NULL)
	{	
		printf("Spazio non disponibile\n\n");
		return(1);
	}

	/** Inizializzazione della scacchiera 2d a zero	**/
	
	for(i=0;i<NR;i++)
	{
		for(j=0;j<NC;j++)
		{
			board2d[i*NR+j]=0;
		}
	}
	
	/** ******************************************************************************************************************************************* **/
	/** Allocazione del database e sua inizializzazione tramite la funzione toggle. L'allocazione avviene secondo lo schema: num_con=2,3,4;			**/
	/** caso=0,1,2,3 corrispondente a orizzontali, verticali, diagonali principali, diagonali secondarie;															**/
	/** configurazione= 0,..., max per caso, esempio: caso=0 configurazioni=0, NR*(NC-(num+2))+1; 																	**/
	/** cella= cella in cui inizia il pattern,...,cella in cui finisce, esempio primo tris orizzontale->cella=0, 1, 2. 										**/
	/** l'indice CELLA indica l'apparteneza di una certa configurazione a quella cella della tabella, così lo stesso bis sarà considerato due volte **/
	/** in quanto a lui apparterranno 2 celle e la differenza tra questi due pattern uguali sarà proprio l'indice cella.										**/
	/** La funzione toggle inizializza solo il primo vettore per ogni configurazione, e poi lo stesso vettore viene copiato negli altri vettori 		**/
	/** appartenenti alla stessa configurazione, riutilizzando le stesse condizioni usate per far variare l'indice CELLA dei singoli vettori del db **/
	/** ******************************************************************************************************************************************* **/
	
	db=(unint *****)malloc(3*sizeof(unint ****));

	for(num_con=0; num_con<3; num_con++)
	{
		db[num_con]=(unint ****)malloc(4*sizeof(unint ***));
		for(caso=0; caso<4; caso++)
		{	
			switch(caso)
			{
				case (0):
					start_cell = 0;
					db[num_con][caso]=(unint ***)malloc(((NR*(NC-(num_con+2)+1)))*sizeof(unint **));
				
					for(config=0; config<(NR*(NC-(num_con+2)+1)); config++)   
					{
						db[num_con][caso][config]=(unint **)malloc((num_con+2)*sizeof(unint *));
						for(cella=start_cell; cella<start_cell+(num_con+2); cella++)
						{
							db[num_con][caso][config][cella]=(unint *)malloc(interi*sizeof(unint));	
							/** Con questo piccolo accorgimento, dopo aver creato i vettori unidimensionali, **/
							/** se è il primo lo inizializzo a quello che voglio io, tramite la funzione toggle **/
							/** altrimenti copio il vettore precedente in quello appena allocato. **/
							/** Ovviamente per precedente si intende quello con indice di cella precedente, ma che appartiene allo stesso pattern **/
							/** Tuttavia mi da segmentation fault all'atto della copia del vettore  **/
							if(cella==start_cell)
							toggle_db(NC, num_con, caso, config, cella, db);
							else
							{
								for(i=0; i<interi; i++)
								{
									db[num_con][caso][config][cella][i] = db[num_con][caso][config][(cella-1)][i];
								}
							}
						}
						if ((start_cell+num_con+2)%NC != 0)
							start_cell++;
						else
							start_cell += num_con+2;
					}
				break;
				
				case (1):
					db[num_con][caso]=(unint ***)malloc((NC*(NR-(num_con+2)+1))*sizeof(unint **));
				
					for(config=0;config<(NC*(NR-(num_con+2)+1));config++)
					{
						db[num_con][caso][config]=(unint **)malloc((num_con+2)*sizeof(unint *));
						for(cella=config;cella<config+NC*(num_con+2);cella+=NC)
						{
							db[num_con][caso][config][cella]=(unint *)malloc(interi*sizeof(unint));
							if(cella==start_cell)
								toggle_db(NC, num_con, caso, config, cella, db);
							else
							{
								for(i=0;i<interi;i++)
								{
									db[num_con][caso][config][cella][i]=db[num_con][caso][config][(cella-NC)][i];
								}
							}
						}
					}
				break;
					
				case (2):
					start_cell=0;
					db[num_con][caso]=(unint ***)malloc(((num_con+2)*((NC-(num_con+2)+1)*(NR-(num_con+2)+1)))*sizeof(unint **));
					
					for(config=0;config<((NC-(num_con+2)+1)*(NR-(num_con+2)+1));config++)
					{
						db[num_con][caso][config]=(unint **)malloc((num_con+2)*sizeof(unint *));
						for(cella=start_cell;cella<start_cell+NC*(num_con+2);cella+=(NC+1))
						{
							db[num_con][caso][config][cella]=(unint *)malloc(interi*sizeof(unint));
							if(cella==start_cell)
								toggle_db(NC, num_con, caso, config, cella, db);
							else
							{
								for(i=0;i<interi;i++)
								{
									db[num_con][caso][config][cella][i]=db[num_con][caso][config][(cella-(NC+1))][i];
								}
							}
						}
						if ((start_cell+num_con+2)%NC != 0)
							start_cell++;
						else
							start_cell += num_con+2;
					}
				break;

				case (3):
					start_cell=num_con+1;
					db[num_con][caso]=(unint ***)malloc(((num_con+2)*((NC-(num_con+2)+1)*(NR-(num_con+2)+1)))*sizeof(unint **));

					for(config=0;config<((NC-(num_con+2)+1)*(NR-(num_con+2)+1));config++)
					{
						db[num_con][caso][config]=(unint **)malloc((num_con+2)*sizeof(unint *));
						for(cella=start_cell;cella<start_cell+(NC-1)*(num_con+2);cella+=(NC-1))
						{
							db[num_con][caso][config][cella]=(unint *)malloc(interi*sizeof(unint));
							if(cella==start_cell)
								toggle_db(NC, num_con, caso, config, cella, db);
							else
							{
								for(i=0;i<interi;i++)
								{
									db[num_con][caso][config][cella][i]=db[num_con][caso][config][(cella-(NC-1))][i];
								}
							}
						}
						if ((start_cell+1)%NC !=0)
							start_cell ++;
						else
							start_cell+=num_con+2;
					}
					break;	
			};
		}
	}
	
	
	/** Disallocazione del database **/
	
	for(num_con=0;num_con<3;num_con++)
	{
		for(caso=0; caso<4; caso++)
		{	
			switch(caso)
			{
				case (0):
					start_cell=0;
					for(config=0;config<(NR*(NC-(num_con+2)+1));config++)   
					{
						for(cella=start_cell;cella<start_cell+(num_con+2);cella++)
						{
							free(db[num_con][caso][config][cella]);
						}
						if ((start_cell+num_con+2)%NC != 0)
							start_cell++;
						else
							start_cell += num_con+2;	
					}
					free(db[num_con][caso][config]);
				break;
				
				case (1):
					for(config=0;config<(NC*(NR-(num_con+2)+1));config++)
					{
						for(cella=config;cella<config+NC*(num_con+2);cella+=NC)
						{
							free(db[num_con][caso][config][cella]);
						}
					}
					free(db[num_con][caso][config]);	
				break;
					
				case (2):
					start_cell=0;		
					for(config=0;config<((NC-(num_con+2)+1)*(NR-(num_con+2)+1));config++)
					{
						for(cella=start_cell;cella<start_cell+NC*(num_con+2);cella+=(NC+1))
						{
							free(db[num_con][caso][config][cella]);
						}
						if ((start_cell+num_con+2)%NC != 0)
							start_cell++;
						else
							start_cell += num_con+2;
					}
					free(db[num_con][caso][config]);			
				break;

				case (3):
					start_cell=num_con+1;
					for(config=0;config<((NC-(num_con+2)+1)*(NR-(num_con+2)+1));config++)
					{
						for(cella=start_cell;cella<start_cell+(NC-1)*(num_con+2);cella+=(NC-1))
						{
							free(db[num_con][caso][config][cella]);
						}
						if ((start_cell+1)%NC !=0)
							start_cell ++;
						else
							start_cell+=num_con+2;
					}
					free(db[num_con][caso][config]);
					break;	
			};
			free(db[num_con][caso]);
		}
		free(db[num_con]);
	}
	free(db);

	return(0);
	
}

void toggle_db (int NC, int pedine, int caso, int config, int cella, unint *****daba)
{
  	int i, s, set_on;																							
	
	switch(caso)
	{
		case(0):
		{
			for(s=cella;s<cella+(pedine+2);s++)
			{
				i= s/(CHAR_BIT*sizeof(unint));
				set_on = s % (CHAR_BIT*sizeof(unint));
				daba[pedine][caso][config][cella][i] |= (1<<set_on);												
			}
		}
		break;
		case(1):
		{
			for(s=cella;s<cella+NC*(pedine+2);s+=NC)
			{
				i= s/(CHAR_BIT*sizeof(unint));
				set_on = s % (CHAR_BIT*sizeof(unint));
				daba[pedine][caso][config][cella][i] |= (1<<set_on);
			}
		}
		break;
		case(2):
		{
			for(s=cella;s<cella+NC*(pedine+2);s+=NC+1)
			{
				i= s/(CHAR_BIT*sizeof(unint));
				set_on = s % (CHAR_BIT*sizeof(unint));
				daba[pedine][caso][config][cella][i] |= (1<<set_on);
			}
		}
		break;
		case(3):
		{
			for(s=cella;s<cella+(NC-1)*(pedine+2);s+=(NC-1))
			{
				i= s/(CHAR_BIT*sizeof(unint));
				set_on = s % (CHAR_BIT*sizeof(unint));
				daba[pedine][caso][config][cella][i] |= (1<<set_on);
			}
		}
		break;
	}													  
}