题目描述:ios
这是一道对于大佬来讲很简单的dp题目,之前原本想作来着,结果由于不会dp因此就直接放弃了,昨天又看到这道题准备把他作了,但是不会dp怎么办啊/最后我求助了lixx大佬帮我梳理了一下思路,而后今天又作了很久,把这道题AC了/不过说实话想通了以后这道题还真不难,可是我作dp的时候一般都想不通qwq。数组
接下来大佬能够自行跳过吼吼吼(๑•̀ㅂ•́)و✧spa
首先咱们把hh[i][j]设为前i道菜、有j元,这样状况下的点菜方法(总感受好像说的很不清楚,但是个人表达能力也就这样了,实在抱歉code
那么咱们能够来模拟一下可能会遇到的状况:买与不买,而买的话又分为两种状况:1.如今的钱恰好能够买一道当前这样的菜。2.如今的钱买完这样的菜以后还剩下一些钱。blog
咱们先来解决不买这种状况,由于不买他只有一种状况比较简单嘛,其实咱们只要添加一句话就行了:继承
hh[i][j]=hh[i-1][j];//继承上一道菜j元时的点菜方法
若是他不买的话就直接继承上一道菜j元时的方法就好了。而他若是买的话也须要继承,只不过还要加一些多出来的方案数,因此咱们直接添加这一句连判断都省了,要买咱们就能够直接添加多出来的方案数。io
可能会有同窗不知道为何要继承上一道菜j元时的方法(会不会有呢?我也不晓得偶),咱们直接继承就表明咱们不买这道菜,不买这道菜方案数就不会增多,因此直接继承就好喽。class
而后接下来咱们来解决第二种状况:买。这种状况可就不能只是一句话了,毕竟他还要加多出来的方案数,可是其实也不难,两个判断就完事:stream
if(j==a[i]) hh[i][j]++;//判断若是如今的钱恰好买第i道菜,刚才咱们已经继承了上一个的方案数,因此咱们如今只用在刚才的基础上+1就好了。 else if(j>a[i]) hh[i][j]+=hh[i-1][j-a[i]];//判断若是如今的钱买完第i道菜还剩下了钱,那么咱们再在刚才的基础上加上剩下的钱能买菜的方案数
可能你们又会疑惑,为何只要i-1的值而不要i-二、i-三、i-4......的值呢?基础
由于i-1的值是当前最准确的值,你想啊,若是i-1的时候恰好又增长了方案数,那你加i-2或者更小的值就会恰好错过这个方案数。仍是那句话,i-1的值是当前最准确的了。
而后应该没有什么疑问了伐(至少我想不到了
那么最后放一个完整代码:
#include<iostream> #include<cstdio> using namespace std; int n,m,a[1100],hh[1100][1100];//数组必定要开1000,我一开始开了100WA了两个点 int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); }//以上为输入 for(int i=1;i<=n;i++){//开始dp循环 for(int j=1;j<=m;j++){ hh[i][j]=hh[i-1][j]; if(j==a[i]) hh[i][j]++; else if(j>a[i]) hh[i][j]+=hh[i-1][j-a[i]]; //上面的我都在以前讲过了,看不懂就怪你喽略略略 } } printf("%d\n",hh[n][m]);//输出 return 0; }