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