草药大师

链接:https://ac.nowcoder.com/acm/problem/235951 来源:牛客网

做法1

因为最大容量有1e9,我们需要剪掉一些情况,对于每次物品我们只能拿一次,那么,其实也是从尾开始跑,只不过我们把从最大容量改成最大能放进的容量,如果总容量减去这一个物品的容量比原先的塞进去的容量大,说明可以拿当前这一个物品,那么就去把这一个物品塞进背包就行。

//本题代码
#include<bits/stdc++.h>
#define endl "\n"
#define int long long
//dont forget to check long long
//别写重变量名
//记得判越界
//别死磕
//处理字符串删掉关流
std::map<int, int> f;
void slove()
{
    int n,s;
    std::cin>>n>>s;
    std::vector<std::pair<int,int>> a(n+1);
    f[0]=0;
    int sum=0;
    for(int i=1;i<=n;i++) 
    {
        int x,y;
        std::cin>>x>>y;
        a[i]={x,y};
        sum+=x;
    }
    int ans=0;
    std::map<int,int>::reverse_iterator it;
    for(int i=1;i<=n;i++)
    {
        for(it=f.rbegin();it!=f.rend();it++)
        {
            if(s-a[i].first>=(*it).first)
            {
                f[(*it).first+a[i].first]=std::max( f[(*it).first+a[i].first], f[(*it).first]+a[i].second);
            }
        }
    }
   for(auto &i:f)
   {
       ans=std::max(ans,i.second);
   }
    std::cout<<ans<<endl;
    

}
signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    int T=1; 
    //std::cin>>T;
    while(T--)    {
        slove();
    }

    return 0;
}

做法2

启发式搜索,单纯的搜索就是在每个物品选与不选做决定,但有些情况是不必要的可以省去,我们只保留那些必要情况,那么什么是必要情况呢,首先考虑拿的话,只要当前的剩余容量还能塞,就塞进去,这是必然的。那不拿这么考虑呢?如果当前这个物品不拿,后面的所有物品尽可能都拿比现在要优,就可以选择不拿,要不然就是必须拿,这样就能减去大多数情况而不影响结果。

//本题代码
#include<bits/stdc++.h>
#define endl "\n"
#define int long long
//dont forget to check long long
//别写重变量名
//记得判越界
//别死磕
//处理字符串删掉关流
struct node{
    int num,t;
    double vaule;
    bool operator <(const node&t){
        return vaule>t.vaule;
    }
}a[510];
int n,m;
int ans=-1;
int f(int dep,int last)
{
    int sum=0;
    for(int i=1;i+dep<=n;i++)
    {
        if(a[i+dep].t<=last) 
        {
            sum+=a[i+dep].num;
            last-=a[i+dep].t;
        }
        else return (int)(sum+a[i+dep].vaule*last);
    }
    return sum;
}
void dfs(int dep,int cur,int last)
{
    ans=std::max(ans,cur);
    if(dep>n) return ;
    if(f(dep,last)+cur>ans) dfs(dep+1,cur,last);
    if(a[dep].t<=last)
    {
        dfs(dep+1,cur+a[dep].num,last-a[dep].t);
    }

}
void slove()
{
   std::cin>>n>>m;
   for(int i=1;i<=n;i++)
   {
        int x,y;
        std::cin>>x>>y;
        a[i]={y,x};
        a[i].vaule=1.0*y/x*1.0;
   }
   std::sort(a+1,a+1+n);
   dfs(1,0,m);
   std::cout<<ans<<endl;

}
signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    int T=1; 
    //std::cin>>T;
    while(T--)    {
        slove();
    }

    return 0;
}