一. 原题链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3631
二. 题意:求最大报销额。
三. 解题过程:乍一看,明显背包问题。好像数据规模有点大,不管,试试再说。然后TLE了。
上网搜一下,DFS加剪枝。你坑爹的枚举怎么有我动态规划快!!!然后事实告诉我们不能死读书。
每次有选择不选择2种状态:拿或者不拿
剪枝:
1、判断拿起来会不会超过最大值M。
2、判断背包数会不会超出N。
3、如果每天报销额加起来小于等于最大值M。直接都不用搜索了。
4、最重要的剪枝:如果当前的价值 + 剩下所有价值 <= M,直接剪枝。
四、优化:先降序排序。你升序也行,不过你要从后面开始搜。为什么要降序排序呢,那是因为最后那个最重要的剪枝,排序后,大的都在前面,那么如果要出现满足第四个剪枝的情况的递归层数也就小了。PS:没优化 1180ms 优化后0ms。
五、代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
int weight[31], ans, N, M, IdOfBag, curValue;
void dfs(int id, int value)
{
ans = ans > value? ans : value;
if(ans == M)
return;
if(id == N)
return;
int tempSum = 0, i;
for(i = id; i < N; i++){
tempSum += weight[i];
}
if(tempSum + value <= M){
value += tempSum;
ans = ans > value? ans : value;
return;
}
if(value + weight[id] <= M){
dfs(id + 1, value + weight[id]);
dfs(id + 1, value);
}
else{
dfs(id + 1, value);
}
}
bool cmp(int a, int b)
{
return a > b;
}
int main()
{
//freopen("in.txt", "r", stdin);
int i , j;
while(cin>>N>>M){
ans = 0;
for(i = 0; i < N; i++){
cin>>weight[i];
ans += weight[i];
}
if(ans <= M){
cout<<ans<<endl;
continue;
}
ans = 0;
IdOfBag = 0;
curValue = 0;
sort(weight, weight + N, cmp);
dfs(IdOfBag, curValue);
cout<<ans<<endl;
}
}
本文介绍了一种利用DFS加剪枝策略解决背包问题的方法,并通过具体实例讲解了如何进行有效剪枝以提高算法效率。文章还分享了通过降序排序进一步优化算法的经验。
274

被折叠的 条评论
为什么被折叠?



