首先要处理好月日转为净天数
给出月和日转化为净天数教程
给出n个物品求最大价值,这明显是01背包,并且他的体积变成了价值有限制。但是又因为有一个相邻日期大于等于K的限制,所以并不是每个物品可以相邻,也就是01背包的动态转移方程为f(i,j)=max(f(i-1,j),f(i-1,j-w)+v) ,当拿走第i个物品时一定考虑他和上一个物品最近日期超过K这一合法性判断,所以我们要预处理每个物品最近日期并且大于等于K天的相邻物品存放到一个数组里,这样每次拿走第i个物品时,只需要从他距离日期最近并且合法的物品转移过来即可。
动态转移方程:f[i][j]=max(f[i-1][j], f[上一次临界合法的发票][j-wi]+vi);
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e4+10;
int n,m,k;
int yue[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int s[20];//存放每月初的净天数
int f[N][N],lst[N];
struct ren{
int m,d,v,t;//月、天、价值、净天数
}d[N];
bool cmp(ren a,ren b){
return a.t<b.t;
}
int main(){
cin>>n>>m>>k;
for(int i=2;i<=12;i++)s[i]=s[i-1]+yue[i-1]; //前缀和处理净天数
for(int i=1;i<=n;i++){
cin>>d[i].m>>d[i].d>>d[i].v;
d[i].t=s[d[i].m]+d[i].d;
}
sort(d+1,d+1+n,cmp);
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(d[i].t-d[j].t>=k)lst[i]=j; //找出距离i最近合法的票据
}
}
//背包dp
for(int i=1;i<=n;i++){
for(int j=m;j>=d[i].v;j--){
f[i][j]=max(f[i-1][j],f[lst[i]][j-d[i].v]+d[i].v);
}
}
cout<<f[n][m]<<endl;
return 0;
}