目录
问题:
思路:
回溯-分支限界法
知识点
目标函数(分支结束的情况): n==0
约束函数(截断不合理的分支): num < 2 、 i >= n-i && num == 0
限界函数(阶段不最优的分支):没有
回溯法代码:
问题:
一个小孩手中有 N 块正方形的积木,他总是想不同的方法来搭建各种
不同的楼梯。他搭建的楼梯必须满足如下条件:
(1)楼梯每个台阶的砖块数不能相同,且严格递减。
(2)每个楼梯至少包含两个台阶。
(3)必须用完所有的积木且只搭建一个楼梯。
请编写程序计算该小孩最多有多少种满足上述条件的不同的搭建方法。
输入要求:
输入 1 行,积木的个数 N,N 大于等于 3。
输出要求:输出 1 行,有多少种不同的楼梯搭建方法。
输入样例:
10
输出样例
9
思路:
回溯-分支限界法
知识点
剪枝函数分为约束函数
和限界函数
约束函数:避免无所谓的搜索那些已知不含答案状态
的子树。
限界函数:用于最优化
问题,剪去那些不可能含有最优答案结点
的子树。
目标函数(分支结束的情况): n==0
约束函数(截断不合理的分支): num < 2 、 i >= n-i && num == 0
限界函数(阶段不最优的分支):没有
回溯法代码:
反着做:
#include<bits/stdc++.h>
using namespace std;int dfs(int n, int last, int num)
{int result = 0;if(n == 0 && num < 2) return 0;if(n == 0 && num >= 2) return 1;for(int i = last+1; i <= n; i++){if(n-i != 0 && i >= n-i) continue;result += dfs(n-i, i, num+1);}return result;
}
int main()
{int n;cin >> n;int result = dfs(n, 0, 0);cout << result << endl;return 0;
}
正着题意做(反常识):
#include<bits/stdc++.h>using namespace std;int solve(int n, int last, int num)
{int result = 0;if(n == 0 && num >= 2) return 1;if(n == 0 && num < 2) return 0;for(int i = 1; i <= last-1; i++){result += solve(n-i, i, num+1);}return result;
}
int main()
{int n;cin >> n;cout << solve(n, n+1, 0) << endl;return 0;
}