动态规划DP入门例题

动态规划典型入门例题

3714:点菜问题

总时间限制: 

1000ms

内存限制: 

65536kB

描述

北大网络实验室经常有活动需要叫外买,但是每次叫外买的报销经费的总额最大为C元,有N种菜可以点
,经过长时间的点菜,网络实验室对于每种菜i都有一个量化的评价分数(表示这个菜可口程度),为Vi,每种菜的价格为Pi, 问如何选择各种菜,使得在报销额度范围内能使点到的菜的总评价分数最大?
注意:由于需要营养多样化,每种菜只能点一次。

输入

输入的第一行有两个整数C(1 <= C <= 1000)和N(1 <= N <= 100),C代表总共能够报销的额度,N>代表能点菜的数目。接下来的N行每行包括两个在1到100之间(包括1和100)的的整数,分别表示菜的>价格和菜的评价分数。

输出

输出只包括一行,这一行只包含一个整数,表示在报销额度范围内,所点的菜得到的最大评价分数。

样例输入

90 4
20 25
30 20
40 50
10 18
40 2
25 30
10 8

样例输出

95
38

递推关系

dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
 取和不取第i个菜两种情况取最大值,dp[i-1][j]表示不取第i种,那么从i-1种菜取放入j容量背包。dp[i-1][j-w[i]]+v[i]表示取第i种菜,那么背包容量j-w[i],但是价值增加w[i].

代码:

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int w[1001];
int v[1001];
int dp[1001][1001];
int main()
{
    int c,n;
    while(cin>>c>>n)
    {
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            cin>>w[i]>>v[i];
        for(int i=1;i<=n;i++)
            for(int j=0;j<=c;j++)
        {
            if(j<w[i])             //背包容量不够第i种菜,则一定是不取
                dp[i][j]=dp[i-1][j];
            else
            {
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
                   /*取和不取第i个菜两种情况取最大值,dp[i-1][j]表示不取第i种,那么从i-1种菜取放入j容量背包。dp[i-1][j-w[i]]+v[i]表示取第i种菜,那么背包容量j-w[i],但是价值增加w[i].*/
            }

        }
        cout<<dp[n][c]<<endl;
    }
    return 0;
}

空间优化

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
int w[1001];
int v[1001];
int dp[1001];
int main()
{
    int c,n;
    while(cin>>c>>n)
    {
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;i++)
            cin>>w[i]>>v[i];
        for(int i=1;i<=n;i++)
            for(int j=c;j>=w[i];j--)
            dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
        cout<<dp[c]<<endl;
    }
    return 0;
}

3727:摘花生

总时间限制: 

1000ms

内存限制: 

65536kB

描述

Hello Kitty 想摘点花生送给她喜欢的米老鼠。她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生。Hello Kitty只能向东或向南走,不能向西或向北走。问Hello Kitty 最多能够摘到多少颗花生。

输入

第一行是一个整数T,代表一共有多少组数据。1<=T <= 100
接下来是T组数据。

每组数据的第一行是两个整数,分别代表花生苗的行数R和列数 C ( 1<= R,C <=100)
每组数据的接下来R行数据,从北向南依次描述每行花生苗的情况。每行数据有 C 个整数,按从西向东的顺序描述了该行每株花生苗上的花生数目 M ( 0<= M <= 1000)。

输出

对每组输入数据,输出一行,内容为Hello Kitty能摘到得最多的花生颗数。

样例输入

2
2 2
1 1
3 4
2 3
2 3 4
1 6 5

样例输出

8
16
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[102][102];
int main()
{
    int r,c;
    int t;
    cin>>t;
    while(t--){
            cin>>r>>c;
        memset(dp,0,sizeof(dp));
        int w[r+2][c+2];
        for(int i=1;i<=r;i++)
            for(int j=1;j<=c;j++)
            cin>>w[i][j];
       dp[1][1]=w[1][1];
       for(int i=2;i<=r;i++)
        dp[i][1]=w[i][1]+dp[i-1][1];
       for(int i=2;i<=c;i++)
        dp[1][i]=w[1][i]+dp[1][i-1];
        for(int i=2;i<=r;i++)
            for(int j=2;j<=c;j++)
            dp[i][j]=max(dp[i-1][j]+w[i][j],dp[i][j-1]+w[i][j]);
        cout<<dp[r][c]<<endl;
    }
    return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值