迭代加深 + 剪枝 + 暴搜
对于本道题目,对一个玩暴搜的新手可能是一道很难的题目, 但更多的是不敢去想,所以,一道题目可能并不是多难, 只是你不敢去想;
好了下面上思路:
这是思路w
既然是暴搜,要啥思路, emmmm,还是扯一点吧;
- 题目要求找到最短长度的结果, 所以每次dfs时需要对搜索的深度(depth)做出限制;
while(!dfs(....)) depth++;
-
接下来是暴搜, 每次找下一位的数, 并保存数据, 如果最后一个数合法, 那么输出结果, 由于深度由小到大增的, 所以第一次搜索到的结果就是最优解
-
剪枝, 剪枝无无非就是优化搜索顺序, 排除等效冗余, 可行性剪枝......
- 限制的深度内没有找到答案,剪!
- 该数字已经被用过,剪!
- 该数字比最大的数字(题目输入的数字)大,剪!
- 该数字比上一个数字小, 剪!
C++代码
#include<iostream>
#include<cstring>
using namespace std;
const int N = 110;
int a[N];
int n;
bool s[N];
bool dfs(int u, int depth)
{
if(u > depth) return false;
if(a[u - 1] == n) return true;
memset(s, 0, sizeof(s));
for(int i = u - 1; i >= 0; i--)
{
for(int j = i; j >= 0; j--)
{
int add = a[i] + a[j];
if(s[add] || add <= a[u - 1] || add > n) continue;
s[add] = true;
a[u] = add;
if(dfs(u + 1, depth)) return true;
}
}
return false;
}
int main()
{
while(cin >> n, n)
{
int depth = 0;
a[0] = 1;
while(!dfs(1, depth)) depth++;
for(int i = 0; i < depth; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
return 0;
}