HDU 5887 Herbs Gathering (超大01背包|dfs+剪枝|map|卡时)

题意:最多100个物品,v和w都<=1e9


思路:

是个超大01背包。这题有好多做法,学到不少东西。

1.dfs+剪枝:我们可以按性价比排序,若剩下的背包空间都以最高性价比选也比我们已知的ans小,则剪枝。

2.map优化dp,见代码

3.按一定贪心策略把更可能是答案的放前面排序后dfs,运行时间达到一定程度则return

if((clock()-startTime)/CLOCKS_PER_SEC > 0.02)return;


dfs+剪枝代码:

#include
using namespace std;
typedef long long ll;
const int maxn = 105;
int n, W;
ll ans;
struct node
{
    int v, w;
    double vw;
    bool operator <(const node &a) const
    {
        return vw > a.vw;
    }
}a[maxn];

void dfs(int cur, ll val, ll cost)
{
    ans = max(ans, val);
    if(cur > n) return ;
    if(cur+1 <= n)
    {
        ll tmp = (W-cost)/a[cur+1].w+1;
        if(val+a[cur+1].v*tmp < ans) return ;
    }
    if(cost+a[cur].w <= W)
        dfs(cur+1, val+a[cur].v, cost+a[cur].w);
    dfs(cur+1, val, cost);
}

int main(void)
{
    while(cin >> n >> W)
    {
        ans = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d", &a[i].w, &a[i].v);
            a[i].vw = 1.0*a[i].v/a[i].w;
        }
        sort(a+1, a+1+n);
        dfs(1, 0, 0);
        printf("%lld\n", ans);
    }
    return 0;
}


map优化dp代码:

#include
using namespace std;
typedef long long ll;
const int maxn = 105;
ll n, W;
struct node
{
    ll v, w;
    bool operator < (const node &a) const
    {
        return w > a.w;
    }
}a[maxn];
map m;
priority_queue pq;

int main(void)
{
    while(cin >> n >> W)
    {
        for(int i = 1; i <= n; i++)
            scanf("%lld%lld", &a[i].w, &a[i].v);
        sort(a+1, a+1+n);
        m.clear(); m[0] = 0;
        while(!pq.empty()) pq.pop();
        ll ans = 0;
        for(int i = 1; i <= n; i++)
        {
            if(a[i].w > W || a[i].v <= 0) continue;
            ll maxx = 0;
            for(map::iterator it = m.begin(); it != m.end(); it++)//遍历可行决策
            {
                ll tw = it->first;
                ll tv = it->second;
                if(tv+a[i].v >= maxx && tw+a[i].w <= W) pq.push(tw+a[i].w);
                maxx = max(maxx, tv+a[i].v);    //单调性优化,保证w增长的同时,v也在增长
            }
            while(!pq.empty())  //不能在遍历决策时进行
            {
                ll tmp = pq.top(); pq.pop();
                m[tmp] = max(m[tmp], m[tmp-a[i].w]+a[i].v);
                ans = max(ans, m[tmp]);
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}



你可能感兴趣的:(DP,贪心,搜索)