P1164 小A点菜

题目描述:

这是一道对于大佬来说很简单的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\n",hh[n][m]);//输出
    return 0;
}

 

以上仅是个人对于这道题的全部思路与想法,如果有什么不对的地方,还请各位大佬及时向我纠正。

 

posted @ 2020-05-22 11:05  dgdger  阅读(228)  评论(0编辑  收藏  举报