根据提供的信息,我们可以总结出以下相关的IT知识点,主要聚焦于搜索算法、动态规划(DP)以及数据结构的应用。 ### 搜索算法与动态规划 #### 1. **深度优先搜索(DFS)** - **概念**:深度优先搜索是一种用于遍历或搜索树或图的算法。在访问起始节点后,算法将选择一个子节点进入,然后从该子节点选择另一个子节点,以此类推,直到达到某个叶子节点。 - **应用**:在题目中,DFS 被用来解决如何用给定的小棍拼凑成特定长度的问题。具体来说,DFS 用来寻找所有可能的组合方式,并检查这些组合是否满足最终的目标长度。 - **优化技巧**: - **剪枝**:为了避免不必要的搜索分支,可以采用“剪枝”技术。比如在代码中,对于已经使用过的小棍不再重复考虑,以及当当前小棍的长度等于剩余所需长度时,可以直接结束该分支的搜索。 - **记忆化搜索**:虽然本例中没有直接使用记忆化搜索,但在复杂问题中使用记忆化搜索可以有效避免重复计算,提高效率。 #### 2. **动态规划(DP)** - **概念**:动态规划是一种通过将问题分解为互相重叠的子问题来求解最优化问题的方法。 - **应用**:尽管提供的代码示例中没有直接使用 DP 方法,但题目中的标签 `dp` 表明,这个问题可以通过 DP 的方法进行优化。例如,可以建立一个状态数组来存储中间结果,避免重复计算,从而达到优化的目的。 ### 数据结构 #### 1. **数组与布尔数组** - **数组**:如 `sticks` 和 `used` 数组分别用来存储小棍的长度和记录哪些小棍已经被使用过。 - **布尔数组**:布尔数组 `used` 被用来标记某个元素是否已被使用。这对于剪枝和避免重复计算至关重要。 #### 2. **排序** - **快速排序**:使用了 C++ STL 中的 `sort` 函数对小棍按长度进行降序排列。这样可以更高效地进行搜索,因为较大的小棍通常会更快达到目标长度或者发现无法达成目标。 ### 具体问题分析 #### 1. **POJ1011 Sticks** - **问题描述**:给定一系列不同长度的小棍,要求从中选择一些小棍拼凑成若干组,每组长度相同且尽可能大。如果无法达到这个要求,则输出所有小棍的总长度。 - **解决方案**: - 使用 DFS 进行搜索,并结合剪枝策略减少不必要的搜索分支。 - 对输入数据进行预处理,包括排序和初始化数据结构。 - 针对每个可能的目标长度进行尝试,直至找到最大可能的分组长度或确定无法进一步分割。 #### 2. **POJ1033 Defragment** - **问题描述**:文件碎片整理问题。给定一组文件片段的原始位置和当前位置,要求重新组织文件片段使得它们按照原始顺序排列。 - **解决方案**: - 使用两个数组 `q` 和 `d` 来记录文件片段的当前位置和原始位置。 - 通过遍历并更新这两个数组,确定哪些文件片段需要移动以及移动的方向。 - 实现了一个简单的算法来检测哪些文件片段需要被移动,并输出相应的操作序列。 通过以上分析可以看出,这些问题都涉及到了计算机科学中的基础算法和数据结构的应用。在实际开发过程中,理解这些基本原理和技术是至关重要的,它们不仅能够帮助开发者解决问题,还能提高程序的效率和可维护性。
这个题目是不是贪心的,我就是第一次用了贪心,一直WA,相当的悲剧,贪心错误的sample:7 15 11 8 8 8 4 3 2 1,所以大家还是全部搜索。但是全部搜索必须剪枝,不然肯定是TLE的,而且本体属于强剪枝,少剪了也是TLE。
经典搜索题,果然是到处充斥着剪枝才能过啊,我的代码离剪到极限还差很多
题目给出一大堆小棍子的长度,需要把他们拼成几根长度相等的大棍子,求大棍子的最短长度
看自己剪枝方法的效果时候,可以添设一个变量来记录递归次数
如剪枝4:没有这个剪枝的情况下对以下数据需要40万次递归,而加上这个剪枝后减少到了4万多次
对数据:
45
15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8 15 3 2 4 11 1 8 8 8
#include <iostream>
#include <algorithm>
using namespace std;
int sticks[65];
int used[65];
int n,len;
bool dfs(int i,int l,int t)//i为当前试取的棍子序号,l为要拼成一根完整的棍子还需要的长度,t初值为所有棍子总长度
{
if(l==0)
{
t-=len;
if(t==0)return true;
used[i]=1; //由于排序过,找到的第一根肯定最长,也肯定要使用,所以从下一根开始搜索
if(dfs(i+1,len-sticks[i],t))return true;
used[i]=0;
t+=len;
}
else
{
for(int j=i;j<n;++j)
{
if(j>0&&(sticks[j]==sticks[j-1]&&!used[j-1])) //剪枝2:前后两根长度相等时,如果前面那根没被使用,也就是由前面那根
continue; //开始搜索不到正确结果,那么再从这根开始也肯定搜索不出正确结果,此剪枝威力较大
if(!used[j]&&l>=sticks[j]) //剪枝3:最简单的剪枝,要拼成一根大棍子还需要的长度L>=当前小棍子长度,才能选用
{
l-=sticks[j];
used[j]=1;
if(dfs(j,l,t))return true;
l+=sticks[j];
used[j]=0;
if(sticks[j]==l) //剪枝4:威力巨大的剪枝,程序要运行到此处说明往下的搜索失败,若本次的小棍长度刚好填满剩下长度,但是后
break; //面的搜索失败,则应该返回上一层
}
}
}
return false;
剩余27页未读,继续阅读
- 粉丝: 1
- 资源: 1
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助