1164 小A点菜
这是不是一个完全背包?在花完的钱数下吃最多的饭,肯定是一个背包
这好像是一个01背包
我们首先设f[i][j]表示i个物品在j元的方案数量
所以,我们就有了三个方程:
1.当前的钱数恰好能买一道菜
2.当前的钱数不够买一道菜
3.当前的钱数超出一道菜
所以通过这三种方程就很好的决定策略了
-------------------重新------------------------
这很明显是一个01背包,把钱花完一分不剩,而且每个菜只有一份
所以就是一个01背包,选或者不选
f[i][j]表示第i道菜在j元的方案数量
属于比较模板的了
1.如果恰好能买,那么直接在前一个的方案加1
2.如果不能买,就直接复合前一个的答案
3如果超出去,因为不能整个整个的买,所以当前的最大方案就是买与不买的方案相加
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;
const int SIZE=10010;
int n,m;
int a[SIZE],f[SIZE][SIZE];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(j==a[i]) f[i][j]=f[i-1][j]+1;//刚好买一道菜
if(j>a[i]) f[i][j]=f[i-1][j]+f[i-1][j-a[i]];//超出价格,需要规划
if(j<a[i]) f[i][j]=f[i-1][j];//不够买
}
}
cout<<f[n][m]<<endl;
return 0;
}
这道题很简单就能AC了,但是我们需要学会下降一个维度,并且这个维度可以让我们减少很多的事情
因为在上一个题中,我们不需要i个数,而只需要i-1所以根本没用,直接省去
我们重新设f[i]表示在i元的最大方案,设边界f[0]=1表示没钱的时候只有一种操作
这个菜的方案数量,就是选这个菜的方案数量加上不选这个菜的方案数量
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
using namespace std;
const int SIZE=10010;
int n,m;
int a[SIZE];
int f[SIZE];//f[i]表示i元的最大价值
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
f[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=m;j>=a[i];j--)
{
f[j]+=f[j-a[i]];//买这个加上不买这个的价值
}
}
cout<<f[m]<<endl;
return 0;
}