题目地址:http://vjudge.net/problem/UVALive-3667
一开始 以为就是DFS搜索,选择题目中给的刻度,一个一个试,最短的的那个就是答案,
而且题目给的刻度是小于等于50的,那很明显可以用二进制压缩
然而 竟然尺子上的刻度不是题目给出的,所以之前枚举都的方法都错了
应该是迭代加深搜索+剪枝
#include <bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=a;i<=(int)(b);++i)
#define REPD(i,a,b) for(int i=a;i>=(int)(b);--i)
typedef long long LL;
int n,a[50+5],dep,ans[10];
int ID[1000000+5];
bool DFS(int cur,LL done){ //从pos位置开始选
if(cur==dep) return done==(1ll<<n)-1;
REP(i,1,cur-1){
REP(j,1,n-1){
if(done&(1ll<<j)) continue;
int m=ans[i]+a[j];
if(m<=ans[cur-1]||m>=a[n]) continue;
LL nd=done;
ans[cur]=m;
REP(k,1,cur-1) {
m=ans[cur]-ans[k];
if(ID[m]) nd|=(1ll<<ID[m]);
}
m=a[n]-ans[cur];
if(ID[m]) nd|=(1ll<<ID[m]);
if(DFS(cur+1,nd)) return true;
}
}
return false;
}
int main(int argc, char const *argv[])
{
int kase=0;
while(scanf("%d",&n)==1&&n){
REP(i,1,n) scanf("%d",&a[i]);
sort(a+1,a+1+n); n=unique(a+1,a+1+n)-a-1;
memset(ID,0,sizeof(ID));
REP(i,1,n) ID[a[i]]=i;
dep=2; ans[1]=0;
while(dep*(dep-1)/2<n) dep++;
while(!DFS(2,1)) dep++;
printf("Case %d:\n%d\n0", ++kase,dep);
ans[dep]=a[n]; //最后一个肯定是a[n];
REP(i,2,dep) printf(" %d", ans[i]);
printf("\n");
}
return 0;
}