题目链接:https://www.luogu.com.cn/problem/P1417
这个题目不是单纯的01背包问题,因为01背包给出的物品的价值是不变的,但是这个题目中物品的价值会随着时间的增长而降低,所以要确定什么优先顺序取(x,y)才会得到更有的结果,所以就涉及到了排序和贪心。还有一点与01背包不痛,完后第n件物品的完成时时间越少越好,因为时间长了之后物品的价值下降,所以最后时刻完成的不一定是最优结果。证明过程如下:(参考洛谷某博客)
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1 13 #define scand(x) scanf("%llf",&x) 14 #define f(i,a,b) for(int i=a;i<=b;i++) 15 #define scan(a) scanf("%d",&a) 16 #define dbg(args) cout<<#args<<":"<<args<<endl; 17 #define inf 0x3f3f3f3f 18 #define maxn 100005 19 int n,m,t; 20 ll dp[maxn]; 21 struct node{ 22 ll a,b,c; 23 }p[maxn]; 24 bool cmp(node& x,node& y) 25 { 26 return x.c*y.b<y.c*x.b;//满足条件的x在前 27 } 28 int main() 29 { 30 //freopen("input.txt","r",stdin); 31 //freopen("output.txt","w",stdout); 32 std::ios::sync_with_stdio(false); 33 scan(t); 34 scan(n); 35 f(i,1,n)scan(p[i].a); 36 f(i,1,n)scan(p[i].b); 37 f(i,1,n)scan(p[i].c); 38 sort(p+1,p+n+1,cmp);//贪心思想,确定优先顺序 39 f(i,1,n) 40 for(int j=t;j>=p[i].c;j--) 41 { 42 dp[j]=max(dp[j],dp[j-p[i].c]+p[i].a-j*p[i].b);//第j时间完成第i件 43 } 44 ll ans=0; 45 f(i,1,t)ans=max(ans,dp[i]);//完成第n件的时间越短,结果可能更优 46 pf("%lld",ans); 47 }