1. 程式人生 > >【洛谷P1417】烹調方案 貪心+背包dp

【洛谷P1417】烹調方案 貪心+背包dp

void urn 設計 pri n) clu can 產生 space

題目大意:一共有 n 件食材,每件食材有三個屬性,ai,bi和ci,如果在t時刻完成第i樣食材則得到ai-t*bi的美味指數,用第i件食材做飯要花去ci的時間。眾所周知,gw的廚藝不怎麽樣,所以他需要你設計烹調方案使得美味指數最大。

題解:這道題需要對背包問題有更加深入的理解。
可以發現,如果不進行排序操作的話,先選的物品會對後續選擇的物品的價值產生影響,即:答案與選擇的先後順序有關。這與 0-1 背包問題不同,對於 0-1 背包問題來說,先選擇的物品對後續物品答案的貢獻沒有影響,因此與選擇的順序無關。對於這種物品之間價值會相互影響的情況,首先考慮固定一個子集,對集合內的元素按某種順序排序,擴展到整個集合來說,即:先進行排序,再進行 dp 即可。

代碼如下

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=55;
const int maxx=1e5+10;

int T,n;
LL dp[maxx];
struct node{int a,b,c;}t[maxn];
bool cmp(const node &x,const node &y){
    return (LL)x.c*y.b<(LL)x.b*y.c;
}

void read_and_parse(){
    scanf("%d%d",&T,&n);
    for(int i=1;i<=n;i++)scanf("%d",&t[i].a);
    for(int i=1;i<=n;i++)scanf("%d",&t[i].b);
    for(int i=1;i<=n;i++)scanf("%d",&t[i].c);
    sort(t+1,t+n+1,cmp);
}
void solve(){
    for(int i=1;i<=n;i++)
        for(int j=T;j>=t[i].c;j--)
            dp[j]=max(dp[j],dp[j-t[i].c]+t[i].a-(LL)t[i].b*j);
    LL ans=0;
    for(int i=0;i<=T;i++)ans=max(ans,dp[i]);
    printf("%lld\n",ans);
}
int main(){
    read_and_parse();
    solve();
    return 0;
}

【洛谷P1417】烹調方案 貪心+背包dp