ybt 1293:买书
OpenJudge NOI 2.6 6049:买书
完全背包求方案数
【解题思路】该问题为完全背包求方案数的问题。
1. 状态定义集合:每种书买多少本构成的方案
限制:在前多少种书中买,买书钱数
属性、条件:书价钱加和等于买书钱数
统计量:方案数
状态定义:dp[i][j]:在前i种书中选书购买,总价钱为j元的方案数
初始状态:在前i种书中选书购买,总价格为0元的方案,就是不选书,有一种方案。即dp[i][0]=1
记a[i]为第i种书的价钱
集合:在前i种书中选择书价钱加和为j的方案
分割集合:是否选择第i种书
- 如果选择一本第i种书,接下来要在前i种书中选择书,价钱加和为j-a[i],方案数为:dp[i][j-a[i]]
- 如果不选择第i种书,接下来要在前i-1种书中选择书,价钱加和为j,方案数为dp[i-1][j]
- 两种情况的方案数加和,为在前i种书中选择书价钱加和为j的方案数,即dp[i][j] = dp[i][j-a[i]] + dp[i-1][j]
可以进行滚动数组优化。
【题解代码】 解法1:基本解法#include解法2:滚动数组优化using namespace std; #define N 15 #define M 1005 int n, m, a[N] = {0, 10, 20, 50, 100};//a[i]:第i本书的钱数 int dp[N][M];//dp[i][j]:在前i种书中选书购买,总价钱为j元的方案数 int main() { m = 4;//书的种类 cin >> n; for(int i = 0; i <= m; ++i) dp[i][0] = 1; for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j) { if(j >= a[i]) dp[i][j] = dp[i][j-a[i]] + dp[i-1][j]; else dp[i][j] = dp[i-1][j]; } cout << dp[m][n]; return 0; }
#includeusing namespace std; #define N 15 #define M 1005 int n, m, a[N] = {0, 10, 20, 50, 100};//a[i]:第i本书的钱数 int dp[M];//dp[i][j]:在前i种书中选书购买,总价钱为j元的方案数 int main() { m = 4;//书的种类 cin >> n; dp[0] = 1; for(int i = 1; i <= m; ++i) for(int j = a[i]; j <= n; ++j) dp[j] = dp[j-a[i]] + dp[j]; cout << dp[n]; return 0; }



