您的位置:首页 > 产品设计 > UI/UE

SPOJ 1771 NQUEEN Yet Another N-Queen Problem

2015-07-29 15:47 288 查看
After solving Solution to the n Queens Puzzle by constructing, LoadingTime wants to solve a harder version
of the N-Queen Problem. Some queens have been set on particular locations on the board in this problem. Can you help him??


Input

The input contains multiple test cases. Every line begins with an integer N (N<=50), then N integers followed, representing the column number of the queen in each rows. If the number is 0, it means no queen has
been set on this row. You can assume there is at least one solution.


Output

For each test case, print a line consists of N numbers separated by spaces, representing the column number of the queen in each row. If there are more than one answer, print any one of them.


Example

Input:
4 0 0 0 0
8 2 0 0 0 4 0 0 0

Output:
2 4 1 3
2 6 1 7 4 8 3 5


n皇后问题,转化为dlx精确覆盖,行列和斜线作为列,不过斜线无需全部覆盖,只是作为约束条件。

转化之前要先剪枝,可以大大减少需要搜索的量.

#include<cstdio>
#include<vector>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll maxn = 5005;
int T, n, m, x, y, t, X, Y,tot,u[maxn],p[maxn][2],vis[maxn];

inline void read(int &ret)
{
	char c;
	do {
		c = getchar();
	} while (c < '0' || c > '9');
	ret = c - '0';
	while ((c = getchar()) >= '0' && c <= '9')
		ret = ret * 10 + (c - '0');
}

struct DLX
{
	#define maxn 50005
	#define F(i,A,s) for (int i=A[s];i!=s;i=A[i])
	int L[maxn], R[maxn], U[maxn], D[maxn];
	int row[maxn], col[maxn], ans[maxn], cnt[maxn];
	int n, m, num, sz;

	void add(int now, int l, int r, int u, int d, int x, int y)
	{
		L[now] = l;	R[now] = r;	U[now] = u;
		D[now] = d;   row[now] = x;  col[now] = y;
	}
	void reset(int n, int m)
	{
		num = 0x7FFFFFFF;
		this->n = n;	this->m = m;
		for (int i = 0; i <= m; i++)
		{
			add(i, i - 1, i + 1, i, i, 0, i);
			cnt[i] = 0;
		}
		L[0] = m; 	R[m] = 0; 	sz = m + 1;
	}
	void insert(int x, int y)
	{
		int ft = sz - 1;
		if (row[ft] != x)
		{
			add(sz, sz, sz, U[y], y, x, y);
			U[D[sz]] = sz; D[U[sz]] = sz;
		}
		else
		{
			add(sz, ft, R[ft], U[y], y, x, y);
			R[L[sz]] = sz; L[R[sz]] = sz;
			U[D[sz]] = sz; D[U[sz]] = sz;
		}
		++cnt[y];	++sz;
	}

	//精确覆盖
	void remove(int now)
	{
		R[L[now]] = R[now];
		L[R[now]] = L[now];
		F(i, D, now) F(j, R, i)
		{
			D[U[j]] = D[j];
			U[D[j]] = U[j];
			--cnt[col[j]];
		}
	}
	void resume(int now)
	{
		F(i, U, now)	F(j, L, i)
		{
			D[U[j]] = j;
			U[D[j]] = j;
			++cnt[col[j]];
		}
		R[L[now]] = now;
		L[R[now]] = now;
	}
	bool dfs(int x)
	{
		//if (x + A() >= num) return;
		if (x==n) { num = min(num, x); return true; }
		int now = R[0];
		if (now>n) return false;
		for (int i=R[0];i<=n;i=R[i]) if (cnt[now]>cnt[i]) now = i;
		remove(now);
		F(i, D, now)
		{
			ans[x] = row[i];
			F(j, R, i) remove(col[j]);
			if (dfs(x + 1)) return true;
			F(j, L, i) resume(col[j]);
		}
		resume(now);
		return false;
	}
	//精确覆盖

	//重复覆盖
	void Remove(int now)
	{
		F(i, D, now)
		{
			L[R[i]] = L[i];
			R[L[i]] = R[i];
		}
	}
	void Resume(int now)
	{
		F(i, U, now) L[R[i]] = R[L[i]] = i;
	}
	int vis[maxn];
	int flag[maxn];
	int A()
	{
		int dis = 0;
		F(i, R, 0) vis[i] = 0;
		F(i, R, 0) if (!vis[i])
		{
			dis++;	vis[i] = 1;
			F(j, D, i) F(k, R, j) vis[col[k]] = 1;
		}
		return dis;
	}
	void Dfs(int x)
	{
		if (!R[0]) num = min(num, x);
		else if (x + A()<num)
		{
			int now = R[0];
			F(i, R, 0) if (cnt[now]>cnt[i]) now = i;
			F(i, D, now)
			{
				Remove(i); F(j, R, i) Remove(j);
				Dfs(x + 1);
				F(j, L, i) Resume(j); Resume(i);
			}
		}
	}
	//重复覆盖

	void display(int x)
	{
		for (int i=0;i<num;i++) u[p[ans[i]][0]]=p[ans[i]][1];
		for (int i=1;i<=x;i++)
		{
			printf("%d%s",u[i],i==x?"\n":" ");
		}
	}
}dlx;

void insert(int x,int y,int z)
{
	int a,b,c,d;
	a=x;
	b=n+y;
	c=n+n+x+y-1;
	d=n+n+n+n-1+(n-x)+y;
	if (vis[a]+vis[b]+vis[c]+vis[d]) return ;
	tot++;
	p[tot][0]=x;
	p[tot][1]=y;
	dlx.insert(tot,a);
	dlx.insert(tot,b);
	dlx.insert(tot,c);
	dlx.insert(tot,d);
	if (z) vis[a]=vis[b]=vis[c]=vis[d]=1;
}

int main()
{
	//read(T);
	while (~scanf("%d", &n))
	{
		tot=0;
		dlx.reset(n,6*n-2);
		memset(vis,0,sizeof(vis));
		for (int i=1;i<=n;i++)
		{
			scanf("%d",&x);
			if (x) insert(i,x,1);
		}
		for (int i=1;i<=n;i++)
			for (int j=1;j<=n;j++) insert(i,j,0);
		if (dlx.dfs(0)) dlx.display(n);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: