题目背景
《爱与愁的故事第四弹·plant》第一章。
题目描述
爱与愁大神后院里种了 n 棵樱花树,每棵都有美学值Ci(0≤Ci≤200)。爱与愁大神在每天上学前都会来赏花。爱与愁大神可是生物学霸,他懂得如何欣赏樱花:一种樱花树看一遍过,一种樱花树最多看 Pi(0≤Pi≤100) 遍,一种樱花树可以看无数遍。但是看每棵樱花树都有一定的时间Ti(0≤Ti≤100)。爱与愁大神离去上学的时间只剩下一小会儿了。求解看哪几棵樱花树能使美学值最高且爱与愁大神能准时(或提早)去上学。
题目限制
输入格式
输出格式
只有一个整数,表示最大美学值。
输入输出样例
解题思路
本题是几个背包问题的综合题,最外层由于在时间消耗和价值外还多了一个观看次数的条件,即总体上是一个二维费用背包。内部当p[ i ]==0时观看次数不限,即为完全背包,否则为多重背包,最后将他们化为01背包的方法求解
AC代码
#include <bits/stdc++.h>
using namespace std;
struct time
{
int h;
int m;
}ts,te;
int timeh(char ch[]);
int timem(char ch[]);
int n,t[10000],c[10000],p[10000],T,dp[1001],v[10000],cn[10000];
char ch1[5],ch2[5];
int main()
{
int count_=0;
while((ch1[count_]=getchar())!=' ') count_++; //现在
count_=0;
while((ch2[count_]=getchar())!=' ') count_++; //上学时间
ts.h=timeh(ch1);
te.h=timeh(ch2);
ts.m=timem(ch1);
te.m=timem(ch2);
T=(te.h-ts.h)*60+(te.m-ts.m); //距离上学还剩多少时间
cin>>n;
for(int i=0;i<n;i++)
{
cin>>t[i]>>c[i]>>p[i];
}
memset(dp,0,sizeof(dp)); //初始dp为0
for(int i=0;i<n;i++)
{
if(p[i]) //如何p[i]>0即为多重背包问题
{
int ct=1,cnt=1,x=p[i];
while(x>=ct)
{
v[cnt]=c[i]*ct;
cn[cnt++]=t[i]*ct;
x-=ct;
ct<<=1;
}
if(x)
{
v[cnt]=c[i]*x;
cn[cnt++]=t[i]*x;
}
for(int k=0;k<cnt;k++) //将多重背包问题化解为01背包
{
for(int j=T;j>=cn[k];j--)
{
dp[j]=max(dp[j],dp[j-cn[k]]+v[k]);
}
}
}
else //p[i]==0为完全背包问题
{
for(int j=t[i];j<=T;j++)
{
dp[j]=max(dp[j],dp[j-t[i]]+c[i]);
}
}
}
cout<<dp[T];
return 0;
}
int timeh(char ch[])
{
int h=0;
if(*(ch+1)>=48&&*(ch+1)<=57)
{
h=(*(ch)-48)*10+*(ch+1)-48;
}
else
h=*(ch)-48;
return h;
}
int timem(char ch[])
{
int m=0;
if(*(ch+1)>=48&&*(ch+1)<=57)
{
m=(*(ch+3)-48)*10+*(ch+4)-48;
}
else
m=(*(ch+2)-48)*10+*(ch+3)-48;
return m;
}