题意:给你n个工作集合,给你T的时间去做它们。给你m和s,说明这个工作集合有m件事可以做,它们是s类的工作集合(s=0,1,2,s=0说明这m件事中最少得做一件,s=1说明这m件事中最多只能做一件,s=2说明这m件事你可以做也可以不做)。再给你ci和gi代表你做这件事要用ci的时间,能获得gi的快乐值。求在T的时间内你能获得的最大快乐值。
思路:分三类各自求即可。0的时候必须更新,1的时候最多更新一次,2的时候正常01背包。
#include<bits/stdc++.h> #define s first #define e second #define rep(i,a,b) for(int i=a;i<=b;i++) #define rep2(i,a,b) for(int i=a;i>=b;i--) #define ll long long using namespace std; const int maxn=110; const int inf=1e9; int dp[maxn],tmp[maxn],c[maxn],g[maxn],T,M; void solve0() //at least { rep(i,0,T) tmp[i]=-inf; rep(i,1,M) rep2(j,T,c[i]){ tmp[j]=max(tmp[j],max(dp[j-c[i]]+g[i],tmp[j-c[i]]+g[i])); } rep(i,0,T) dp[i]=tmp[i]; } void solve1() //at most { rep(i,0,T) tmp[i]=dp[i]; rep(i,1,M) rep2(j,T,c[i]) dp[j]=max(tmp[j-c[i]]+g[i],dp[j]); } void solve2() //free { rep(i,1,M) rep2(j,T,c[i]) dp[j]=max(dp[j-c[i]]+g[i],dp[j]); } int main() { int N,S,ans; while(~scanf("%d%d",&N,&T)){ memset(dp,0,sizeof(dp)); ans=-1; rep(i,1,N){ scanf("%d%d",&M,&S); rep(j,1,M) scanf("%d%d",&c[j],&g[j]); if(S==0) solve0(); if(S==1) solve1(); if(S==2) solve2(); } ans=max(ans,dp[T]); printf("%d\n",ans); } return 0; }
原文地址:https://www.cnblogs.com/hua-dong/p/11184959.html
时间: 2024-10-29 19:06:43