tips:
回溯
use a queue to restore the temporary marked array(vis) , and when it back, set vis = 0
first floor give out all the received res, and combine with all the d to make new res, and mark all length which can get then,
code:
<pre name="code" class="cpp">#include<cstdio>
#include<cmath>
#include<string>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 55;
int d[maxn], vis[maxn];
int pos[1000005];
int n, len;
int res[maxn];
bool dfs(int cnt) {
if(cnt == len) {
for(int i=1; i<n; i++) {
if(!vis[i]) return false;
}
return true;
}
queue<int> q;
for(int i=1; i<cnt; i++) {
for(int j=1; j<n; j++) {
if(!vis[j]) {
int temp = res[i]+d[j];
if(temp <= res[cnt-1] || temp >= d[n])continue;
//make sure that the new answer is biger than ever
res[cnt] = temp;
for(int k=1; k<cnt; k++) {
temp = res[cnt]-res[k];
if(vis[pos[temp]]==0 && pos[temp]) {
q.push(pos[temp]);
vis[pos[temp]] = 1;
}
}
temp = d[n]-res[cnt];
if(!vis[pos[temp]] && pos[temp]) {
vis[pos[temp]] = 1;
q.push(pos[temp]);
}
if(dfs(cnt+1)) return true;
while(!q.empty()) {
vis[q.front()]=0;
q.pop();
}
}
}
}
return false;
}
int main() {
int kase=1;
while(scanf("%d", &n) != EOF && n) {
memset(vis, 0 ,sizeof(vis));
memset(pos, 0, sizeof(pos));
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;
for (int i = 1; i <= n; i++)
pos[d[i]] = i;
len = sqrt(2 * n) - 1;
res[1] = 0;
while (!dfs(2))
len++;
res[len] = d[n];
printf("Case %d:\n", kase++);
printf("%d\n", len);
for (int i = 1; i <= len; i++)
printf("%d ", res[i]);
printf("\n");
}
return 0;
}