题意:2021年,n个人过生日,做蛋糕需要天,生日那天给第i个人有个好感度,也可以选择送礼物,需要花元,获得个好感度,每个礼物最多买一次。在生日当天做蛋糕,如果只要一天也能赶上。
思路:
2021年不会出现2月29
假设给i个人做蛋糕,j个人发礼物是最优的
我们可以爆搜求出表示给j个人发礼物能得到的最大好感度
然后用动态规划求出给i个人做蛋糕,j个人发礼物能得到的最大好感度,当然还要加上一个时间t表示提前多少天开始做蛋糕
MyCode:
#include <bits/stdc++.h> using namespace std; const int maxn=1e6+7,maxm=2e5+7,N=1e5+7; typedef long long int ll; typedef unsigned long long ull; struct node { int m,d,day,v,at; bool operator<(const node& a)const { return at<a.at; } } pp[505]; int d[20],n,m,w,a[20],b[20],dp[20][370]; void dfs(int i,int cnt,int now,int v) { if(v>d[cnt]) d[cnt]=v; if(i==m) return; int ans(0); if(now>=a[i]) dfs(i+1,cnt+1,now-a[i],v+b[i]); dfs(i+1,cnt,now,v); } int mon[13]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int main() { int T; scanf("%d",&T); for(int i=1; i<=12; ++i) mon[i]=mon[i]+mon[i-1]; while(T--) { scanf("%d%d%d",&n,&m,&w); memset(d,0,sizeof d); memset(dp,0,sizeof dp); for(int i=1; i<=n; ++i) { scanf("%*d-%d-%d %d %d",&pp[i].m,&pp[i].d,&pp[i].day,&pp[i].v); if(pp[i].m==2&&pp[i].d==29) { --i, --n; } pp[i].at=mon[pp[i].m-1]+pp[i].d; } for(int i=0; i<m; ++i) scanf("%d%d",&a[i],&b[i]); dfs(0,0,w,0); sort(pp+1,pp+1+n); while (!d[m]) --m; int ans(0); for(int i=1; i<=n; ++i) for(int k=m; ~k; --k) for(int t=pp[i].at; ~t; --t) { if(t>=pp[i].day) dp[k][t]=max(dp[k][t],dp[k][t-pp[i].day]+pp[i].v);//做蛋糕 if(k) dp[k][t]=max(dp[k][t],dp[k-1][t]-d[k-1]+d[k]);//不做第i个人的生日蛋糕 ans=max(ans,dp[k][t]); } printf("%d\n",ans); } return 0;; }