【NOI2005】【DLX】智慧珠游戏(code)

首先吐槽题目名称:


我想了好久zhzyx是什么...跪跪跪跪跪跪

然后写了个弱B的搜索样例都要2.5s 跪跪跪跪跪跪

然后学了N久的DLX..跪跪跪跪跪跪


总之给邓大牛跪了!膜拜瞬秒DLX的!


Introduction:

之所以叫DLX是因为像跳舞?(雾)

但无论如何Dancing Links is a useful tool which is used to solve a kind of problem called 'exact cover'.

See the PDF here (Chinese ver.)


So how can we use it in this problem? (NOI2005 zhzyx)


其实很简单,但是如果你是第一次做此类题目,那你肯定会很难想到。

把每一个未被覆盖的点(x,y)转化成矩阵的一列,每一种零件的每一种可能的摆放形式转化为占矩阵中的一行, 把其占用的(x,y)格子标记为1,然后再把所有还没有固定的零件每个做一列,把所有属于该基本零件的摆放方式的行标记为1。

所以您大概就知道怎么做了吧..(恕我表达能力有限吧)


然后具体的步骤请看论文吧。


给个code(注意赋初值,你要先考虑一下(0, 0)的编号)


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<cmath>
#include<cctype>
#include<bitset>
using namespace std;

const int tt[61][6][2] =
{
	{{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
	{{3, 0}, {0, 0}, {0, 1}, {1, 0}, {0, 0}, {0, 0}},
	{{3, 0}, {0, 0}, {0, 1}, {1, 1}, {0, 0}, {0, 0}},
	{{3, 0}, {0, 0}, {1, 0}, {1, 1}, {0, 0}, {0, 0}},
	{{3, 0}, {0, 1}, {1, 0}, {1, 1}, {0, 0}, {0, 0}},
	{{4, 0}, {0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 0}},
	{{4, 0}, {0, 0}, {1, 0}, {2, 0}, {3, 0}, {0, 0}},
	{{4, 0}, {0, 0}, {0, 1}, {0, 2}, {1, 0}, {0, 0}},
	{{4, 0}, {0, 0}, {0, 1}, {0, 2}, {1, 2}, {0, 0}},
	{{4, 0}, {0, 0}, {1, 0}, {1, 1}, {1, 2}, {0, 0}},
	{{4, 0}, {0, 2}, {1, 0}, {1, 1}, {1, 2}, {0, 0}},
	{{4, 0}, {0, 0}, {1, 0}, {2, 0}, {0, 1}, {0, 0}},
	{{4, 0}, {0, 0}, {1, 0}, {2, 0}, {2, 1}, {0, 0}},
	{{4, 0}, {0, 0}, {0, 1}, {1, 1}, {2, 1}, {0, 0}},
	{{4, 0}, {0, 1}, {1, 1}, {2, 1}, {2, 0}, {0, 0}},	
	{{4, 0}, {0, 0}, {0, 1}, {1, 0}, {1, 1}, {0, 0}},		
	{{5, 0}, {0, 0}, {0, 1}, {0, 2}, {1, 0}, {2, 0}},
	{{5, 0}, {0, 0}, {0, 1}, {0, 2}, {1, 2}, {2, 2}},
	{{5, 0}, {0, 0}, {1, 0}, {2, 0}, {2, 1}, {2, 2}},
	{{5, 0}, {0, 2}, {1, 2}, {2, 0}, {2, 1}, {2, 2}},
	{{5, 0}, {0, 0}, {0, 1}, {0, 2}, {0, 3}, {1, 1}},
	{{5, 0}, {0, 0}, {0, 1}, {0, 2}, {0, 3}, {1, 2}},
	{{5, 0}, {1, 0}, {1, 1}, {1, 2}, {1, 3}, {0, 1}},
	{{5, 0}, {1, 0}, {1, 1}, {1, 2}, {1, 3}, {0, 2}},		 
	{{5, 0}, {0, 0}, {1, 0}, {2, 0}, {3, 0}, {1, 1}},
	{{5, 0}, {0, 0}, {1, 0}, {2, 0}, {3, 0}, {2, 1}},
	{{5, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {1, 0}},
	{{5, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {2, 0}},
	{{5, 0}, {0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 2}},
	{{5, 0}, {0, 0}, {0, 2}, {1, 0}, {1, 1}, {1, 2}},
	{{5, 0}, {0, 0}, {0, 1}, {1, 0}, {2, 0}, {2, 1}},
	{{5, 0}, {0, 0}, {0, 1}, {1, 1}, {2, 0}, {2, 1}},
	{{5, 0}, {0, 0}, {0, 1}, {1, 0}, {1, 1}, {0, 2}},
	{{5, 0}, {0, 0}, {0, 1}, {1, 0}, {1, 1}, {1, 2}},
	{{5, 0}, {0, 0}, {0, 1}, {1, 0}, {1, 1}, {2, 0}},
	{{5, 0}, {0, 0}, {0, 1}, {1, 0}, {1, 1}, {2, 1}},
	{{5, 0}, {0, 0}, {1, 0}, {1, 1}, {2, 0}, {2, 1}},
	{{5, 0}, {0, 1}, {1, 0}, {1, 1}, {2, 0}, {2, 1}},
	{{5, 0}, {0, 0}, {0, 1}, {0, 2}, {1, 1}, {1, 2}},
	{{5, 0}, {1, 0}, {0, 1}, {0, 2}, {1, 1}, {1, 2}},
	{{5, 0}, {0, 1}, {0, 2}, {0, 3}, {1, 0}, {1, 1}},
	{{5, 0}, {0, 0}, {0, 1}, {0, 2}, {1, 2}, {1, 3}},
	{{5, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 2}, {1, 3}},
	{{5, 0}, {1, 0}, {1, 1}, {1, 2}, {0, 2}, {0, 3}},
	{{5, 0}, {0, 1}, {1, 1}, {2, 1}, {2, 0}, {3, 0}},
	{{5, 0}, {0, 0}, {1, 0}, {2, 0}, {2, 1}, {3, 1}},
	{{5, 0}, {0, 0}, {1, 0}, {1, 1}, {2, 1}, {3, 1}},
	{{5, 0}, {0, 1}, {1, 1}, {1, 0}, {2, 0}, {3, 0}},
	{{5, 0}, {0, 1}, {1, 0}, {1, 1}, {1, 2}, {2, 1}},
	{{5, 0}, {0, 1}, {0, 2}, {1, 0}, {2, 0}, {1, 1}},
	{{5, 0}, {0, 0}, {0, 1}, {1, 1}, {1, 2}, {2, 2}},
	{{5, 0}, {0, 0}, {1, 0}, {1, 1}, {2, 1}, {2, 2}},
	{{5, 0}, {0, 2}, {1, 1}, {1, 2}, {2, 0}, {2, 1}},
	{{5, 0}, {0, 0}, {0, 1}, {0, 2}, {0, 3}, {1, 0}},
	{{5, 0}, {0, 0}, {0, 1}, {0, 2}, {0, 3}, {1, 3}},
	{{5, 0}, {1, 0}, {1, 1}, {1, 2}, {1, 3}, {0, 0}},
	{{5, 0}, {1, 0}, {1, 1}, {1, 2}, {1, 3}, {0, 3}},			 
	{{5, 0}, {0, 0}, {1, 0}, {2, 0}, {3, 0}, {0, 1}},
	{{5, 0}, {0, 0}, {1, 0}, {2, 0}, {3, 0}, {3, 1}},
	{{5, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {0, 0}},
	{{5, 0}, {0, 1}, {1, 1}, {2, 1}, {3, 1}, {3, 0}}
};

const int t[13][2] = 
{
	{0, 0}, {1, 4}, {5, 6}, {7, 14}, {15, 15}, {16, 19}, {20, 27}, 
	{28, 31}, {32, 39}, {40, 47}, {48, 48}, {49, 52}, {53, 60}
};
			  
const int ft[61] = 
{
	0, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 
	6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 
	9, 9, 9, 9, 9, 9, 9, 9, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12
};

const int tooo[78] = 
{
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12
};
	
char m1[12][12];

bool use[11][11];
bool choose[3005];

int d[350005], u[350005], r[350005], l[350005], col[350005], row[350005], size[105];
int done[13];
int mtx[3005][70];
int btl[11][11], ltb[60][2], ctl[100], map[11][11];
int h, z, node;
int xx[3005], yy[3005], nn[3005];
int num, que[100];

void init()
{
	memset(done, 0, sizeof(done));
   freopen("zhzyx.in", "r", stdin);
	for (int i = 1; i <= 10; i++) 
	{
		gets(m1[i]);
		for (int j = 1; j <= i; j++)
		{
			map[i][j] = tooo[(int)m1[i][j - 1]];
			if (map[i][j]) use[i][j] = 1, done[map[i][j]] = 1;
		}
	}
}

bool check(int k, int x, int y)
{
	for (int i = 1; i <= tt[k][0][0]; i++)
		if (use[x + tt[k][i][0]][y + tt[k][i][1]] || x + tt[k][i][0] < y + tt[k][i][1] || x + tt[k][i][0] > 10) return 0;
	return 1;
}

void prepare()
{
	h = 0;
	for (int i = 1; i <= 10; i++)
		for (int j = 1; j <= i; j++)
			if (!use[i][j])
				btl[i][j] = ++h;
	for (int i = 1; i <= 12; i++)
		if (!done[i])
			ctl[i] = ++h;
	z = 0;
	memset(mtx, 0, sizeof(mtx));
	for (int i = 1; i <= 12; i++)
		if (!done[i])
			for (int j = t[i][0]; j <= t[i][1]; j++)
				for (int x = 1; x <= 10; x++)
					for (int y = 1; y <= x; y++)
						if (check(j, x, y))
						{
							mtx[++z][ctl[i]] = 1;
							xx[z] = x; yy[z] = y; nn[z] = j;
							for (int k = 1; k <= tt[j][0][0]; k++)
								mtx[z][btl[x + tt[j][k][0]][y + tt[j][k][1]]] = 1;
						}
}


void build(int line)
{
	for (int i = 1; i <= num; ++i, ++node)
	{
		int p = que[i];
		size[p]++;
		row[node] = line;
		col[node] = p;
		d[node] = p;
		u[node] = u[p];
		d[u[node]] = node;
		u[d[node]] = node;
		if (i == 1) r[node] = node, l[node] = node;
		else
		{
			l[node] = node - 1;
			r[node] = node - i + 1;
			l[r[node]] = node;
			r[l[node]] = node;
		}
	}
}

void addp()
{
	node = h + 1;
	memset(r, -1, sizeof(r));
	memset(l, -1, sizeof(r));
	memset(u, -1, sizeof(r));
	memset(d, -1, sizeof(r));
	for (int i = 1; i <= h; i++)
		r[i - 1] = i, l[i] = i - 1, u[i] = i, d[i] = i, row[i] = 0, col[i] = i, size[i] = 1;
	r[h] = 0; l[0] = h; u[0] = 0; d[0] = 0; col[0] = 0; row[0] = 0;

	for (int i = 1; i <= z; ++i)
	{
		num = 0;
		for (int j = 1; j <= h; ++j)
			if (mtx[i][j]) que[++num] = j;
		build(i);
	}
}

void remove(int k)
{
	r[l[k]] = r[k]; l[r[k]] = l[k];
	for (int i = d[k]; i != k; i = d[i])
		for (int j = r[i]; j != i; j = r[j])
		{
			u[d[j]] = u[j];
			d[u[j]] = d[j];
			size[col[j]]--;
		}
}
void resume(int k)
{
	for (int i = u[k]; i != k; i = u[i])
		for (int j = l[i]; j != i; j = l[j])
			size[col[u[d[j]] = d[u[j]] = j]]++;
	l[r[k]] = r[l[k]] = k;
}
bool dfs(int k)
{
	if (r[0] == 0) return 1;
	int mini = INT_MAX, pos = 0;
	for (int i = r[0]; i != 0; i = r[i])
		if (size[i] < mini) mini = size[i], pos = i;
	remove(pos);
	for (int p = d[pos]; p != pos; p = d[p])
	{
		choose[row[p]] = 1;
		for (int q = r[p]; q != p; q = r[q]) remove(col[q]);
		if (dfs(k + 1)) return 1;
		choose[row[p]] = 0;
		for (int q = l[p]; q != p; q = l[q]) resume(col[q]);
	}
	resume(pos);
	return 0;
}
void fill(int k, int x, int y)
{
	for (int i = 1; i <= tt[k][0][0]; i++)
		map[x + tt[k][i][0]][y + tt[k][i][1]] = ft[k];
}

void outit()
{
   freopen("zhzyx.out", "w", stdout);
	if (dfs(1))
	{
		for (int i = 1; i <= 3005; i++) if (choose[i]) fill(nn[i], xx[i], yy[i]);
		for (int i = 1; i <= 10; i++)
		{
			for (int j = 1; j <= i; j++) printf("%c", (char)map[i][j] + 64);
			printf("\n");
		}
	}
	else cout<<"No solution"<<endl;
	exit(0);
}

int main()
{
   init();
	prepare();
	addp();
	outit();
   return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

emoizhang

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值