uvalive3667(深搜)

题意:

要求给一个尺子刻m个刻度,给出n种距离,都可以由这m个刻度直接量出来,比如你刻了10,15;那么你也可以直接量出5;求最少刻几个刻度,并且尺子尽量短,给出刻度的位置;刻度数<=7,且一定有0:

思路:

这题我们可以确定两个,一个是0,另一个是最大的那个;

然后因为刻度最大是7个;我们可以从2开始到7枚举;

然后dfs判断是否可以;判断过程就是把枚举要求的长度刻进去,并且刻了之后,与其他所有已经有的刻度相加减得到可以得到的刻度也标记;

当我们刻的数量达到我们所枚举的m,判断是不是所有刻度都有了.


AC代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int N,M;
int d[55], ans[10], num[1000010], vis[55], cnt;
bool dfs(int u){
	if (u == cnt){
		for (int i = 1; i <= N - 1; i++)
			if (!vis[i])
			   	return false;
		return true;
	}
	for (int i = 1; i <= u -1; i++)
		for (int j = 1; j <= N - 1; j++){
			if (!vis[j]){
				int dd = ans[i] + d[j];
				if (dd >= d[N] || dd <= ans[u -1]) continue;
				ans[u] = dd;
				queue<int>q;
				for (int k = 1; k <= u -1; k++){
					dd = ans[u] - ans[k];
					if (num[dd] && !vis[num[dd]]){
						vis[num[dd]] = true;
						q.push(num[dd]);
					}
				}
				dd = d[N] - ans[u];
				if (num[dd] && !vis[num[dd]]){
					vis[num[dd]] = true;
					q.push(num[dd]);
				}
				if (dfs(u + 1)) 
					return true;
				while (!q.empty()){
					vis[q.front()] = false;
					q.pop();
				}
			}
		}
	return false;
}
int main() {
	int cas = 1;
	while (scanf("%d",&N) && N){
		for (int i =1 ; i <= N; i++) 
			scanf("%d",&d[i]);
		sort(d + 1,d + 1 + N);
		N = unique(d + 1, d + 1 + N) - d - 1;
		memset(num,0,sizeof(num));
		memset(vis,false,sizeof(vis));
		for (int i = 1; i <= N; i++) num[d[i]] = i;
		cnt = 2;
		while (cnt * (cnt - 1) / 2 < N) cnt++;
		ans[1] = 0;
		while (!dfs(2)) cnt++;
		ans[cnt] = d[N];
		printf("Case %d:\n",cas++);
		printf("%d\n",cnt);
		for (int i =1; i <= cnt; i++) 
			printf("%d ",ans[i]);
		printf("\n");
	}
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值