1. 程式人生 > >洛谷 P1164 小A點菜

洛谷 P1164 小A點菜

題目連結:https://www.luogu.org/problemnew/show/P1164
思路:可用動態規劃解決,對於每個a[i]有選和不選兩種情況,用dp(i,j)代表到當前第i層揹包容量(可以裝的錢數)為j時可能的情況數,由此寫出狀態轉移方程:dp(i,j)=dp(i-1,j)(上一層揹包容量為j時的情況數,也就是不選菜品a[i]的情況數)+dp(i-1,j-a[i]) (上一層揹包容量為j-a[i]的情況數,也就是本層選擇菜品a[i]的情況數)

c++程式碼:

#include <iostream>
#include <cstring>

using namespace std;

const int maxn=1005;

int  dp[105][maxn];
int a[105];

int main() {
    int n,m;
    cin >> n >> m;
    for(int i=1;i<=n;i++)
       cin >> a[i];
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=n;i++) {
        for(int j=0;j<=m;j++) {
            if(j==a[i])dp[i][j]=dp[i-1][j]+1;
            else if(j>a[i])dp[i][j]=dp[i-1][j]+dp[i-1][j-a[i]];
            else if(j<a[i])dp[i][j]=dp[i-1][j];
        }
    }
    cout <<dp[n][m] << endl;
    return 0;
}

滑動陣列優化空間:

#include <iostream>
#include <cstring>

using namespace std;

const int maxn=1005;

int  dp[maxn];
int a[105];

int main() {
	int n,m;
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	   cin >> a[i];
	memset(dp,0,sizeof(dp));
    dp[0]=1;//每次j==a[i]時,dp[j]+=1 
    for(int i=1;i<=n;i++)
      for(int j=m;j>=a[i];j--)
         dp[j]+=dp[j-a[i]];//是dp(i-1,j)+dp(i-1,j-a[i])的簡寫形式 
	cout <<dp[m] << endl;
	return 0;
}