1164 小A点菜

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值