https://cn.vjudge.net/problem/UVA-529
容易想到用搜索做.比较难想的是:构造一个a数组记录每个小于n的数要经过多少个数列项之后才能到达n.这样做的好处是便于最优性剪枝:如果发现[当前数列长度]加上[至少还需要的数列长度]已经超过了当前最优解则剪枝.
之后就是按题意常规dfs.
#include <bits/stdc++.h>
using namespace std;
const int maxn = 105;
int n, best, cur[maxn], now[maxn], a[maxn<<1];
void dfs(int dep)
{
if (dep + a[cur[dep]] >= best) return;
if (cur[dep] == n)
{
best = dep;
memcpy(now, cur, (dep+1) * sizeof(int));
return;
}
for (int i = dep; i >= 0; --i)
for (int j = dep; j >= i; --j)
{
cur[dep+1] = cur[i] + cur[j];
if (cur[dep+1] > cur[dep] && cur[dep+1] <= n)
dfs(dep+1);
}
}
int main()
{
while (cin >> n && n)
{
for (int i = (n<<1); i >= n; --i) a[i] = 0;
for (int i = n-1; i >= 1; --i) a[i] = a[i<<1]+1;
best = 0x3f3f3f3f;
cur[0] = 1;
dfs(0);
for (int i = 0; i < best; ++i)
printf("%d ", now[i]);
printf("%d\n", now[best]);
}
return 0;
}