恶补一下DP专题(刷刷水题)

开心的金明
题目大意

就是求一定背包容量的最大值

思路

想必大家都知道,一看到这种题目,就会想起01背包

虽然特别简单但是还是讲一下吧

状态设置

由于这题差不多是一个01背包的版子题,那么我们就只需要一个一维的数组去记录状态

f[i]中i代表的是背包容量,而f[i]的值则代表该容量下的最大值

转移方程

f[i]=max(f[i],f[i-背包容量]+背包价值)

输出

输出的话我们就只需要输出f[背包容量]就可以啦

这个简单的DP题就讲完啦

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m;
int f[300010];
int scan()
{
    int as=0,fin=1;
    char c=getchar();
    while(c<'0'||c>'9'&&c!='-') c=getchar();
    if(c=='-') fin=-1;
    while(c>='0'&&c<='9') as=(as<<3)+(as<<1)+c-'0',c=getchar();
    return as*fin;    
}
struct ss
{
    int val,wei;
}a[30];
int main()
{
    n=scan();m=scan();
    for(int i=1;i<=m;i++)
    {
        a[i].wei=scan();
        a[i].val=scan();
        a[i].val*=a[i].wei;
        //    cout<<a[i].val<<endl;
    }
    for(int i=1;i<=m;i++)
    {
        for(int j=n;j>=a[i].wei;j--)
        {
            if(j>=a[i].wei)
                f[j]=max(f[j],f[j-a[i].wei]+a[i].val);
        }
    }
    cout<<f[n];
    return 0;
}
/*
思路
我们设置一个f[i];其中i代表背包的容量
就这样子吧..........
为什么我初始化一个负数就wrong了2333
呜呜..
*/
代码在这里

小A点菜
 题目大意

就是要求花光所有钱的方案数

思路

最开始我还不懂,发现题解的说法好有道理

我们设置一个二维数组来统计选到第i种物品花j的钱的方案数

最后我们就只要输出选到第n种物品话光全部钱的方案数

状态设置

f[i][j]中i代表现在选到第几种物品,j代表花的钱数

转移方程

1.如果我们枚举的钱数大于菜的价格即(j>a[i])

f[i][j]=f[i-1][j]+f[i-1][j-a[i]];//这2个式子相加分别代表不选这种物品和选这种物品,但是价格不变的方案数

2.如果我们枚举的钱数等于菜的价格即(j==a[i])

f[i][j]=f[i-1][j]+1//这2个值相加代表不选这种物品和选的方案数,由于我们不方便将f[i][0]定义为1,所以这里就特判处理一下(是这么理解的吧...)

3.如果小于

f[i][j]=f[i-1][j]//直接转移过来就可以啦

输出

直接输出f[n][m]

#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[1005];
int f[110][10010];
int scan()//快读撒
{
    int as=0,fin=1;
    char c=getchar();
    while(c<'0'||c>'9'&&c!='-') c=getchar();
    if(c=='-') fin=-1;
    while(c>='0'&&c<='9')
    {
        as=(as<<3)+(as<<1)+c-'0';
        c=getchar();
    }
    return as;
}
int main()
{
    n=scan();
    m=scan();
    for(int i=1;i<=n;i++)
    {
        a[i]=scan();
//        cout<<a[i]<<endl;
    }
    for(int i=1;i<=n;i++)//在这里面,i就像一个分层,所以我们没有必要倒着来
    {
        for(int j=1;j<=m;j++)
            {
                if(j>a[i]) f[i][j]=f[i-1][j]+f[i-1][j-a[i]];
                else if(j==a[i]) f[i][j]=f[i-1][j]+1;
                else  f[i][j]=f[i-1][j];
                //        cout<<i<<" "<<j<<" "<<f[i][j]<<endl;
            }
    }
    cout<<f[n][m];
    return 0;
}
/*
思路:
这题的话最开始有点蒙
现在来理一下思路
1.我们设置状态f[i][j],i是前i中,j是前,值为种数
2.
f[i][j]=f[i-1][j]+f[i-1][j-a[i]];//这种转移只是一个向前走的过程
f[i][j]=f[i-1][j]+1;//这种是方案添加
f[i][j]=f[i-1][j];//相当于不选择这种商品
大概是这样子吧
......... 
DP还是要多练一练啊
*/
代码在这里

猜你喜欢

转载自www.cnblogs.com/KSTT/p/10333223.html