最小长度电路板排列问题

85287 Ronnoc 10348 GNU C++ Accepted 1284KB 46ms 2979B 2013-07-31 01:02:09.0

题目链接http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=10348

终于过了。。。

本来是过了多校03的1003想找个排列计数问题乱搞的

结果搜到了这道题

觉得还有点意思

然后就从11点坑到了现在

还好终于过了

可以去睡了orz

还是觉得要记录下来

这货明显是个存在性搜索。。。

貌似出个结果也只是来个记录数组在update的时候更新下,没什么意思,虽然有这个略微加强版的题,但没兴趣了

check是输出当前的排列的结果

IDA是个贪心,出个大概结果

getbest是寻找当前有了一部分ch的最小可能结果(关键剪枝函数)

match数组表示这个点可能的最左差值点

那个小于t+1是核心

	for(i=1;i<=m;i++)
		if(match[i]

虽然夜已深,但是能过,就好

like AC best

PS: 昨天多校水爆了。。。orz


#include 
#include 
#include 
#include 
using namespace std;
int ch[23];
int n, m;
vectorN[23];
vectorB[23];
int res;
int check() {
	int local[23];
	int i, j;
	for (i = 1; i <= m; i++) local[ch[i]] = i;
	int ret = 1;
	for (i = 1; i <= n; i++) {
		int xmin = 23, xmax = -1;
		for (j = 0; j < N[i].size(); j++) xmin = min (xmin, local[N[i][j]]);
		for (j = 0; j < N[i].size(); j++) xmax = max (xmax, local[N[i][j]]);
		ret = max (ret, xmax - xmin + 1);
		}
	return ret;
	}
int IDA (int t, int x) {
	ch[t] = x;
	int i, j, k;
	int did[23];
	for (i = 1; i <= m; i++) did[i] = 0;
	for (i = 1; i <= t; i++) did[ch[i]] = 1;
	for (j = t + 1; j <= m; j++) {
		int ok = 0;
		for (i = 0; !ok && i < B[ch[j - 1]].size(); i++) {
			int q = B[ch[j - 1]][i];
			for (k = 0; !ok && k < N[q].size(); k++) {
				if (!did[N[q][k]]) {
					ok = 1;
					did[N[q][k]] = 1;
					ch[j] = N[q][k];
					}
				}
			}
		if (!ok) {
			for (i = 1; i <= m; i++) {
				if (!did[i]) {
					ch[j] = i;
					did[i] = 1;
					break;
					}
				}
			}
		}
	return check();
	}
int get_best (int t, int x) {
	ch[t] = x;
	int local[23];
	int i, j;
	for (i = 1; i <= m; i++) local[i] = t + 1;
	for (i = 1; i <= t; i++) local[ch[i]] = i;
	int match[23];
	for(i=1;i<=m;i++)match[i]=23;
	int ret = 1;
	vectorL;
	L.clear();
	for (i = 1; i <= n; i++) {
		int xmin = 23, xmax = -1;
		for (j = 0; j < N[i].size(); j++) xmin = min (xmin, local[N[i][j]]);
		for (j = 0; j < N[i].size(); j++) xmax = max (xmax, local[N[i][j]]);
		for (j = 0; j < N[i].size(); j++) 
			if(local[N[i][j]]==t+1)
				match[N[i][j]]=min(match[N[i][j]],xmin);
		ret = max (ret, xmax - xmin + 1);
		}
	for(i=1;i<=m;i++)
		if(match[i] m) res = min (res, check());
	else {
		int ida[23];
		int i, j;
		for (i = 1; i <= m; i++) ida[i] = 23;
		for (i = 1; i <= m; i++)
			if (can (t, i))
				ida[i] = get_best (t, i);	//neerly impossible best
		vector >L;
		for (i = 1; i <= m; i++)
			if (ida[i] != 23) L.push_back (make_pair (ida[i], i));
		sort (L.begin(), L.end());
		for (i = 0; i < L.size(); i++)
			if (get_best (t, L[i].second) < res) {
				ch[t] = L[i].second;
				dfs (t + 1);
				}
		}
	}
int main() {
	int i, j;
	while (cin >> m >> n) {
		for (i = 1; i <= n; i++) N[i].clear();
		for (j = 1; j <= m; j++) B[j].clear();
		for (j = 1; j <= m; j++) {
			for (i = 1; i <= n; i++) {
				int x;
				cin >> x;
				if (x) {
					B[j].push_back (i);
					N[i].push_back (j);
					}
				}
			}
		res = IDA (1, 1);
		dfs (0);
		cout << res - 1 << endl;
		}
	return 0;
	}


你可能感兴趣的:(最小长度电路板排列问题)