刷题Day12小A点菜(动态规划)

前言

 看到这道题以后第一反应是基础递归策略,但是被hack数据卡了时间以后才想到,用DP才能过,否则会被一直卡时间复杂度。毕竟递归下去的时间复杂度为 O ( 2 n ) O(2^n) O(2n).。
 先放题目位置:P1164 小A点菜

下面这个是关键:
然后这里可以放一下这个hack数据:
在这里插入图片描述
所以,递归来做肯定是会TLE的

递归式的得出:

 因为有两个变量,N,M这两个变量分别代表了有的菜品个数,以及手上有的钱;这样的话记f[N,M]为在第1到N道菜品中,手上有M元的时候一共可选的方案总数。初始当N=0或者M=0的时候,按照意义来说,是0,但是在M的0的额时候,N从0到n都应该置为1(这个要从后面递推的时候才能发现)。然后,对于f[N,M]考虑第N道菜品,它既可能取也可能不取,当取的时候,其刚好与f[N-1,M-a[N]]的方案数差不多(因为刚好取用完),当不取的时候,对应的方案数为f[N-1,M]。这样,可以得到递推关系为:
          f [ N , M ] = f [ N − 1 , M − a [ N ] ] + f [ N − 1 , M ] f[N,M]=f[N-1,M-a[N]]+f[N-1,M] f[N,M]=f[N1,Ma[N]]+f[N1,M]
 然后这里就可以看到,当m+a[N]的时候,M-a[N]为0,但是这是可以取的且方案数为1,所以,在之前的说明中将M=0的那一列置为1.通过这个递推式一直从 f [ 1 , 1 ] f[1,1] f[1,1]计算到 f [ N , M ] f[N,M] f[N,M]且最终的 f [ N , M ] f[N,M] f[N,M]即为结果。
 最后给出我的AC代码:

#include <stdio.h>
#include <stdlib.h>



int main(int argc, char *argv[]) {
	int N,M,i,j;

	scanf("%d%d",&N,&M);
	int a[N+1];
	for(i=1;i<=N;i++)
	  scanf("%d",&a[i]);
	int f[N+1][M+1];
	for(i=1;i<=M;i++)
	  f[0][i]=0;
	for(i=0;i<=N;i++)
	  f[i][0]=1;
	for(i=1;i<=N;i++)
	  for(j=1;j<=M;j++){
	  	if(j-a[i]<0)
	  	  f[i][j]=f[i-1][j]+0;
	  	else
	  	  f[i][j]=f[i-1][j]+f[i-1][j-a[i]];
	  }
	printf("%d",f[N][M]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值