原题:
有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40。John现在有n个想要得到的物品,每个物品的体积分别是a1,a2……an。John可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,John就可以得到这些物品。现在的问题是,John有多少种不同的选择物品的方式。
一个背包问题 依然是两种解决办法 递推和动归
总感觉递推比较好理解,这道题问的是有多少种方式。状态转移方程:dp(x-1,y-a[i])or dp(x-1, y) x代表物品编号 y代表重量 a是储存重量的数组。可以不选该物品或者选择后重量减去当前物品重量。
#include <iostream>
using namespace std;
#define MAXN 50
int a[MAXN];
int dp(int x, int y){
if(x < 0){
return 0;
}
if(y == 0){
return 1;
}
return dp(x - 1, y) + dp(x - 1, y - a[x]);
}
int main(int argc, const char * argv[]) {
int n, i;
scanf("%d", &n);
for( i = 1; i <= n; i ++){
scanf("%d", &a[i]);
getchar();
}
printf("%d\n", dp(n, 40));
return 0;
}*/
动态规划,要定义二维数组,
dp[w][k]就是从第k个物品开始取得重量为w的方法个数,依然是选或者不选两种情况 但是这两种情况不应该是并列关系吗?这里似乎是先不选 再讨论选?
可以这样想,就理解了:
if( w-a[k] >= 0){
dp[w][k] = dp[w][k-1]+ dp[w-a[k]][k-1];
}
else dp[w][k] = dp[w][k-1];
#include <iostream>
using namespacestd;
#define MAXN 50
int a[MAXN], dp[MAXN][MAXN];
int main(){
int n, i, w, k;
scanf("%d", &n);
memset(dp,0,sizeof(dp));
for( i =1; i <= n; i ++){
scanf("%d", &a[i]);
getchar();
}
for( i =1; i <= n; i++){
dp[0][i] =1;
}
dp[0][0] =1;
for( w =1; w <= 40; w ++){
for( k =1; k <= n; k ++){
dp[w][k] =dp[w][k - 1];//??????????????
if(w >=a[k]){
dp[w][k] +=dp[w - a[k]][k -1];
}
}
}
printf("%d\n",dp[40][n]);
}