POJ 3740 Easy Finding (Exact cover problem)

 Basic and obvious exact cover problem, using Dancing Links Algorithm (DLX).

 DLX reference: Dancing Links.pdf

#include <stdio.h>

const int MAXM = 20;
const int MAXN = 400;

int U[MAXM*MAXN], D[MAXM*MAXN], L[MAXM*MAXN],
    R[MAXM*MAXN], C[MAXM*MAXN], X[MAXM*MAXN];
int H[MAXM], S[MAXN], Q[MAXM];
int size, n, m;

void init(int r, int c)
{
    for(int i = 0; i <= c; ++i)
	{
		S[i] = 0;
		D[i] = U[i] = i;
		R[i] = i + 1;
		L[i+1] = i;
	}
	R[size = c] = 0;
	while(r)	H[r--] = -1;
}

void remove(int c)
{
	R[L[c]] = R[c], L[R[c]] = L[c];
	for(int i = D[c]; i != c; i = D[i])
		for(int j = R[i]; j != i; j = R[j])
			U[D[j]] = U[j], D[U[j]] = D[j], --S[C[j]];
}

void resume(int c)
{
	R[L[c]] = L[R[c]] = c;
	for(int i = U[c]; i != c; i = U[i])
		for(int j = L[i]; j != i; j = L[j])
			++S[C[U[D[j]] = D[U[j]] = j]];
}

bool Dance(int k)
{
	if(k > m)
		return false;
	int i, j, temp, c;
	if(!R[0])
	{
		return true;;
	}
	for(temp = MAXN * MAXM, i = R[0]; i; i = R[i])
		if(S[i] < temp)
			temp = S[c = i];
	remove(c);
	for(i = D[c]; i != c; i = D[i])
	{
		Q[k] = i;
		for(j = R[i]; j != i; j = R[j])
			remove(C[j]);
		if(Dance(k+1))
			return true;
		for(j = L[i]; j != i; j = L[j])
			resume(C[j]);
	}
	resume(c);
	return false;
}

void Link(int r, int c)
{
	++size;
	C[size] = c;
	X[size] = r;
	++S[c];
	
	D[size] = D[c];
	U[D[c]] = size;
	U[size] = c;
	D[c] = size;
	if(H[r] < 0)
		H[r] = L[size] = R[size] = size;
	else
	{
		R[size] = R[H[r]];
		L[R[H[r]]] = size;
		L[size] = H[r];
		R[H[r]] = size;
	}
}

int main()
{
	while(scanf("%d%d", &m, &n) == 2)
	{
		if(!m && !n)
			break;
		init(m, n);
		for(int i = 1; i <= m; ++i)
			for(int j = 1; j <= n; ++j)
			{
				int c;
				scanf("%d", &c);
				if(c == 1)
					Link(i, j);
			}
		bool flag = true;
		for(int i = 1; i <= n; ++i)
			if(S[i] == 0)
				flag = false;
		if(flag && Dance(0))
			printf("Yes, I found it\n");
		else
			printf("It is impossible\n");
	}
	return 0;
}

  

posted @ 2012-08-08 22:50  georgechen_ena  阅读(262)  评论(0编辑  收藏  举报