题意:
要求给一个尺子刻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;
}