题目描述:
这是一道对于大佬来说很简单的dp题目,以前本来想做来着,结果因为不会dp所以就直接放弃了,昨天又看到这道题准备把他做了,可是不会dp怎么办啊/最后我求助了lixx大佬帮我梳理了一下思路,然后今天又做了好久,把这道题AC了/不过说实话想通了之后这道题还真不难,但是我做dp的时候通常都想不通qwq。
接下来大佬可以自行跳过吼吼吼(๑•̀ㅂ•́)و✧
首先我们把hh[i][j]设为前i道菜、有j元,这样情况下的点菜方法(总感觉好像说的很不清楚,可是我的表达能力也就这样了,实在抱歉
那么我们可以来模拟一下可能会遇到的情况:买与不买,而买的话又分为两种情况:1.现在的钱刚好可以买一道当前这样的菜。2.现在的钱买完这样的菜之后还剩下一些钱。
我们先来解决不买这种情况,因为不买他只有一种情况比较简单嘛,其实我们只要添加一句话就好了:
hh[i][j]=hh[i-1][j];//继承上一道菜j元时的点菜方法
如果他不买的话就直接继承上一道菜j元时的方法就行了。而他如果买的话也需要继承,只不过还要加一些多出来的方案数,所以我们直接添加这一句连判断都省了,要买我们就可以直接添加多出来的方案数。
可能会有同学不知道为什么要继承上一道菜j元时的方法(会不会有呢?我也不晓得偶),我们直接继承就代表我们不买这道菜,不买这道菜方案数就不会增多,所以直接继承就好喽。
然后接下来我们来解决第二种情况:买。这种情况可就不能只是一句话了,毕竟他还要加多出来的方案数,但是其实也不难,两个判断就完事:
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-2、i-3、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 ",hh[n][m]);//输出 return 0; }