hdu 5887 Herbs Gathering (dfs+剪枝 or 超大01背包)

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5887

 

题解:这题一看像是背包但是显然背包容量太大了所以可以考虑用dfs+剪枝,贪心得到的不一定是正确答案。当然这题还可以用背包来写,其实这就用到了dp的一些优化就是存状态,递推过程中有些状态是多余的没必要计算这样就可以大大减少空间的利用和时间的浪费

第一份是dfs+剪枝的写法第二份是背包+map存状态的写法。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
struct TnT {
    ll val , ti;
    double r;
}T[123];
ll ans;
int cnt , n;
ll w;
bool cmp(TnT x , TnT y) {
    return x.r > y.r;
}
int check(int i , ll sum_val , ll sum_ti) {
    for(int j = i ; j < cnt && sum_ti < w ; j++) {
        if(sum_ti + T[j].ti <= w) sum_val += T[j].val , sum_ti += T[j].ti;
        else {
            sum_val += (w - sum_ti) * T[j].r;
            break;
        }
    }
    return sum_val > ans;
}
void dfs(int i , ll sum_val , ll sum_ti) {
    ans = max(ans , sum_val);
    if(i < cnt && check(i , sum_val , sum_ti)) {
        if(sum_ti + T[i].ti <= w) dfs(i + 1 , sum_val + T[i].val , sum_ti + T[i].ti);
        dfs(i + 1 , sum_val , sum_ti);
    }
}
int main() {
    while(~scanf("%d%lld" , &n , &w)) {
        cnt = 0;
        for(int i = 0 ; i < n ; i++) {
            ll x , y;
            scanf("%lld%lld" , &x , &y);
            if(x <= w) T[cnt].ti = x , T[cnt].val = y , T[cnt++].r = (y * 1.0) / (x * 1.0);
        }
        sort(T , T + cnt , cmp);
        ans = 0;
        dfs(0 , 0 , 0);
        printf("%lld\n" , ans);
    }
    return 0;
}
#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
struct TnT {
    int ti , val;
}T[123];
map<int , ll>mmp;
bool cmp(TnT x , TnT y) {
    return x.ti < y.ti;
}
int main() {
    int n , w;
    while(~scanf("%d%d" , &n , &w)) {
        for(int i = 0 ; i < n ; i++) {
            scanf("%d%d" , &T[i].ti , &T[i].val);
        }
        mmp.clear();
        mmp[0] = 0;
        queue<int>q;
        ll ans = 0;
        sort(T , T + n , cmp);
        for(int i = 0 ; i < n ; i++) {
            if(T[i].val == 0 || T[i].ti > w) continue;
            ll Max = 0;
            for(map<int , ll> ::iterator it = mmp.begin() ; it != mmp.end() ; it++) {
                if(it->first + T[i].ti <= w && Max < it->second + T[i].val) {
                    Max = max(Max , it->second + T[i].val);
                    q.push(it->first + T[i].ti);
                }
            }
            while(!q.empty()) {
                int gg = q.front();
                q.pop();
                mmp[gg] = max(mmp[gg] , mmp[gg - T[i].ti] + T[i].val);
                ans = max(ans , mmp[gg]);
            }
        }
        printf("%lld\n" , ans);
    }
    return 0;
}

 

posted @ 2017-10-19 22:01  Gealo  阅读(371)  评论(0编辑  收藏  举报