题目:
思路:
//该动归的状态设置为从前k个愿望中挑选剩余时间i金钱j所实现的愿望个数
//很明显 这里的限制条件有了金钱和时间 另外加上愿望数量 从而dp数组扩展到了三维
//dp[i][j][k]代表的是从前k个愿望中剩余时间i和金钱j 所能实现的愿望个数
核心套路(动归通用):
①先判断党当前剩余的钱和时间是否满足当下的愿望k(即第k个愿望) 如果不满足 则当前状态等于前k-1愿望个数
②否则进行判断当前 “选择第k个愿望”和“不选择第k个愿望”哪个更大,取最大值
对应代码如下:
if(i>=ti[k]&&j>=mo[k]){ //代表时间金钱足够 dp[i][j][k]=max(dp[i][j][k-1],dp[i-ti[k]][j-mo[k]][k-1]+1); //对于k挑选和不挑中二选1 }else{ //代表当前愿望k无法满足 直接跳到下一个愿望 dp[i][j][k]=dp[i][j][k-1]; //没花钱和时间 并且愿望数也没增加 }
完整代码:
#include<iostream> #include<algorithm> using namespace std; int dp[205][205][105]={0}; //确保了边缘赋值的情况 int mo[105]; int ti[105]; int n,m,t; int main(){ cin>>n>>m>>t; for(int i=1;i<=n;i++){ cin>>mo[i]>>ti[i]; } for(int i=0;i<=t;i++){ //dp三个状态分量 所以三重循环 for(int j=0;j<=m;j++){ for(int k=1;k<=n;k++){ if(i>=ti[k]&&j>=mo[k]){ //代表时间金钱足够 dp[i][j][k]=max(dp[i][j][k-1],dp[i-ti[k]][j-mo[k]][k-1]+1); //对于k挑选和不挑中二选1 }else{ //代表当前愿望k无法满足 直接跳到下一个愿望 dp[i][j][k]=dp[i][j][k-1]; //没花钱和时间 并且愿望数也没增加 } } } } cout<<dp[t][m][n]; //最终状态 return 0; }