P1164 小A點菜

題目描述: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;
}

 

以上僅是我的對於這道題的所有思路與想法,若是有什麼不對的地方,還請各位大佬及時向我糾正。

相關文章
相關標籤/搜索