题目
现在的时间是t1,要上学的时间是t2,现在有n棵樱花树,每颗樱花树都有美学值且有一定的观看次数(1到100或无穷),观看一颗樱花树能获得这棵樱花树的美学值,且观看一颗樱花树需要消耗一定的时间,求上学前我们能得到的最大美学值。
思路
dp[i]表示过了i分钟能获得的最大美学值,对于状态转移,首先dp[i]至少等于dp[i-1],然后我们枚举每一种可以在i时间内观看完的樱花树,且该樱花树的观看次数没使用完,假设当前枚举到的樱花树为j,其观看时间为t,美学值为v,dp[i]=max(dp[i],dp[i-t]+v)。
因为要判断一颗樱花树的观看次数是否使用完,我们维护另一个数组flw[i][j],表示过了i分钟取得最大美学值时j樱花树还能观看多少次,其状态转移分两种情况:第一种,dp[i]仍然等于dp[i-1],此时的flw[i][j]和flw[i-1][j]是相同的,第二种,此时dp[i]=dp[i-t]+v,那么flw[i][j]等于flw[i-t][j],最后将flw[i][k]--,k是上面所说拥有美学值v的樱花树。
下面代码中flw[i][j].num就是发挥了第二段的作用。
代码
#include <bits/stdc++.h>
using namespace std;
typedef struct sakura{
int t,v,num;
}sakura;
sakura flw[1005][10005];
int dp[1005];
int main(){
int stime,etime,n,temp;
scanf("%d:%d",&stime,&temp);
stime=stime*60+temp;
scanf("%d:%d",&etime,&temp);
etime=etime*60+temp;
cin>>n;
for(int i=0;i<n;i++){
cin>>flw[0][i].t>>flw[0][i].v>>flw[0][i].num;
if(flw[0][i].num==0)flw[0][i].num=-1;
}
int TIME = etime-stime;
for(int i=1;i<=TIME;i++){
dp[i]=dp[i-1];
int add = i-1;
int add2 = n;
for(int j=0;j<n;j++){
if(flw[0][j].t>i)continue;
if(dp[i-flw[0][j].t]+flw[0][j].v>dp[i]&&flw[i-flw[0][j].t][j].num!=0){
if(flw[i-flw[0][j].t][j].num==0);
else {
dp[i]=dp[i-flw[0][j].t]+flw[0][j].v;
add=i-flw[0][j].t;
add2=j;
}
}
}
for(int j=0;j<n;j++){
flw[i][j]=flw[add][j];
}
flw[i][add2].num--;
}
cout<<dp[TIME];
}