LA 3667 Ruler 搜索

题意:

给出\(n\)个长度,要设计一个有\(m\)个刻度的刻度尺,刻度尺的刻度从\(0\)开始.
使得任意一个长度都能被该刻度尺度量出来.
首先要使\(m\)最小,在\(m\)最小的前提下尺子的长度越短越好.

分析:

首先对长度从小到大排个序,然后从小到大枚举刻度尺上可能的长度,然后用bitset标记一下能被度量的长度有哪些.
注意有可能存在相同的长度.

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <bitset>
#include <iostream>
using namespace std;

const int maxn = 50 + 10;
const int INF = 0x3f3f3f3f;

int n, a[maxn];
int choose[maxn], scale[maxn];
int ans, maxl;

void dfs(int d, bitset<maxn> mask) {
	if(d > ans) return ;
	int cnt = mask.count();
	if(cnt == n) {
		if(d < ans || (d == ans && choose[d-1] < maxl)) {
			ans = d;
			maxl = choose[d - 1];
			for(int i = 0; i < d; i++) scale[i] = choose[i];
		}
		return ;
	}
	if(d == 7) return ;
	for(int i = 0; i < n; i++) if(mask[i] == 0) {
		for(int j = 0; j < d; j++) {
			if(choose[j] + a[i] > choose[d - 1]) {
				choose[d] = choose[j] + a[i];
				bitset<maxn> _mask = mask;
				for(int k = 0; k < d; k++) {
					int t = choose[d] - choose[k];
					for(int l = 0; l < n; l++)
						if(a[l] == t) _mask[l] = 1;
				}
				dfs(d + 1, _mask);
			}
		}
	}
}

int main()
{
	choose[0] = 0;

	int kase = 0;
	while(scanf("%d", &n) == 1 && n) {
		for(int i = 0; i < n; i++) scanf("%d", a + i);
		sort(a, a + n);
		choose[1] = a[0];
		bitset<maxn> mask;
		mask.reset();
		for(int i = 0; i < n; i++) if(a[i] == a[0]) mask[i] = 1;
		ans = INF;
		dfs(2, mask);

		printf("Case %d:\n", ++kase);
		printf("%d\n", ans);
		printf("%d", scale[0]);
		for(int i = 1; i < ans; i++) printf(" %d", scale[i]);
		printf("\n");
	}

	return 0;
}
posted @ 2015-10-24 22:32  AOQNRMGYXLMV  阅读(432)  评论(0编辑  收藏  举报