洛谷 P1164 小A點菜
阿新 • • 發佈:2018-12-21
題目連結: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; }