P1855 榨取kkksc03

题目:

传送门

 

思路:

//该动归的状态设置为从前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;
}

 

 
posted @ 2020-10-12 20:25  neverstopcoding  阅读(225)  评论(0编辑  收藏  举报