http://acm.pku.edu.cn/JudgeOnline/problem?id=1162

http://acm.pku.edu.cn/JudgeOnline/images/1162_1.jpg

Код:
#include <iostream>
using namespace std;
typedef int Coordinates;
struct BasicBlock;
struct BasicBlock {
	int n; // number of blocks
	Coordinates p1, p2, p3; // block coordinates
};
struct BlockSet {
	int n; // number of blocks
	bool o[4096]; // if the corrisponding coordinates is occupided by a block
};
int cur[3]; Coordinates pos;
BasicBlock bb[106] = {{4,256,512,513},
{4,16,17,18},
{4,256,272,528},
{4,1,2,18},
{4,16,32,48},
{4,1,16,17},
{4,1,2,16},
{4,16,17,32},
{4,15,16,31},
{4,240,241,256},
{4,1,16,272},
{4,240,255,256},
{4,256,272,288},
{4,16,32,288},
{4,255,256,257},
{4,1,2,257},
{4,224,240,256},
{4,1,16,256},
{4,1,257,273},
{4,1,2,3},
{4,256,512,768},
{4,16,256,272},
{4,1,256,257},
{4,1,17,33},
{4,256,512,528},
{4,1,2,256},
{4,1,2,17},
{4,240,256,272},
{4,256,257,512},
{4,1,17,18},
{4,16,272,288},
{4,255,256,511},
{4,256,257,273},
{4,256,271,272},
{4,1,256,272},
{4,1,17,256},
{4,256,272,273},
{4,1,240,256},
{4,240,256,257},
{4,15,16,272},
{4,255,256,272},
{4,16,256,257},
{4,16,17,273},
{4,15,16,271},
{4,1,241,257},
{4,16,272,273},
{4,1,15,16},
{4,14,15,16},
{4,16,32,256},
{4,1,257,513},
{4,256,511,512},
{4,1,256,512},
{4,240,256,512},
{4,239,240,256},
{4,15,16,32},
{4,256,272,512},
{4,16,271,272},
{4,256,257,272},
{4,240,256,496},
{4,1,257,258},
{4,1,255,256},
{4,16,17,33},
{4,16,255,256},
{4,1,16,257},
{4,239,255,256},
{4,1,17,273},
{4,16,17,256},
{4,15,16,256},
{4,256,257,513},
{4,16,240,256},
{4,255,256,271},
{4,254,255,256},
{4,241,256,257},
{4,1,2,258},
{4,16,17,272},
{4,1,17,257},
{4,16,31,32},
{4,1,16,32},
{4,16,32,33},
{4,16,272,528},
{4,256,257,258},
{4,16,32,272},
{4,255,256,512},
{4,256,496,512},
{4,16,256,512},
{4,15,16,17},
{3,1,256,0},
{3,1,16,0},
{3,240,256,0},
{3,16,272,0},
{3,255,256,0},
{3,16,17,0},
{3,256,257,0},
{3,15,16,0},
{3,1,257,0},
{3,16,256,0},
{3,256,272,0},
{3,1,17,0},
{3,256,512,0},
{3,1,2,0},
{3,16,32,0},
{2,1,0,0},
{2,256,0,0},
{2,16,0,0},
{1,0,0,0},
{1,0,0,0}};
int best; // best possible solution
int cbest; // current best solution
BlockSet bs;
void Slove(int level) {
	if ( cbest==best ) return;
	if ( (bs.n+3)/4 + level >= cbest ) return;
	if ( bs.n==0 ) { cbest = level; return; }
	// find the block with the minimum index
	pos = (cur[0]<<8) + (cur[1]<<4) + cur[2];
	while ( !bs.o[pos] ) {
cur[2]++;
if ( cur[2]==8 ) { cur[2] = 1; cur[1]++;
	if ( cur[1]==8 ) { cur[1] = 1; cur[0]++; }
}
pos = (cur[0]<<8) + (cur[1]<<4) + cur[2];
	}
	// try each building block
	for ( BasicBlock *end=&(bb[105]), *i=bb; i<end; i++) {
if ( bs.o[pos+i->p1] && bs.o[pos+i->p2] && bs.o[pos+i->p3] ) { // can place
	int x =cur[0], y = cur[1], z = cur[2], bakpos = pos;
	bs.o[pos] = bs.o[pos+i->p1] = bs.o[pos+i->p2] = bs.o[pos+i->p3] = false; // place
	bs.n -= i->n;
	Slove(level+1); // recursion
	cur[0] = x; cur[1] = y; cur[2] = z; pos = bakpos;
	bs.o[pos] = bs.o[pos+i->p1] = bs.o[pos+i->p2] = bs.o[pos+i->p3] = true; // undo place
	bs.n += i->n;
}
	}
}
int main() {
	int i, j, k, l;
	for ( i=0; i<4096; i++) bs.o[i] = false;
	cin>>bs.n; best = (bs.n+3)/4;
	for ( l=0; l<bs.n; l++) {
cin>>i>>j>>k;
bs.o[(i<<8)+(j<<4)+k] = true;
	}
	cur[0] = cur[1] = cur[2] = 1;
	cbest = 100;
	Slove(0);
	cout<<cbest;
	return 0;
}