计算机考研复试--牛客网--C语言练习--Day3

  1. 1 背景
  2. 2 题目:神奇的口袋
    1. 题目描述
    2. 输入描述:
    3. 输出描述:
    4. 示例1
      1. 输入
      2. 输出
    5. 代码1(递归)
    6. 代码2(动态规划)
  3. 3 分析

1 背景

第3天的题目涉及到动态规划了,真是有点难度了……

2 题目:神奇的口袋

题目描述

有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40。John现在有n个想要得到的物品,每个物品的体积分别是a1,a2……an。John可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,John就可以得到这些物品。现在的问题是,John有多少种不同的选择物品的方式。

输入描述:

输入的第一行是正整数n (1 <= n <= 20),表示不同的物品的数目。接下来的n行,每行有一个1到40之间的正整数,分别给出a1,a2……an的值。

输出描述:

输出不同的选择物品的方式的数目。

示例1

输入

3
20
20
20

输出

3

代码1(递归)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#递归实现

#include <stdio.h>
int count(int i, int sum);
int a[100];
int n = 1;
int main() {
while(scanf("%d\n", &n) != EOF) {
for(int i = 0; i < n; i++)
scanf("%d\n", &a[i]);
printf("%d", count(0, 40));
}
return 0;
}
int count(int i, int sum){
if(sum == 0) //找到一组和为sum的组合数
return 1;
if(i == n || sum < 0) //i==n说明没有其他的数来组合,sum<0说明组合不出
return 0;
return
//从数组的第i为开始,包含a[i],和不包含a[i]
count(i + 1, sum - a[i]) + count(i + 1, sum);
}

代码2(动态规划)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#动态规划

#include <stdio.h>
int main() {
int n;
int arr[21];
int dp[25][45]; //dp[i][j]代表前i个物品凑出j体积,共有多少种方法
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &arr[i]);
dp[i][0] = 1; //初始化边界
}
dp[0][0] = 1; //初始化边界
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= 40; j++) {
dp[i][j] = dp[i-1][j]; //默认没有新的组合方式
if(arr[i] <= j) {
dp[i][j] += dp[i-1][j-arr[i]]; //经判断有新的组合方式
}
}
}
printf("%d\n", dp[n][40]);
return 0;
}

3 分析

  • 递归函数注意出口的实现
  • 利用EOF来表示没有输入结束,比如while(scanf(“%d\n”, &n) != EOF)
  • 动态规划还是挺有难度的,看来得好好复习算法了

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 xingshuaikun@163.com。

×

喜欢就点赞,疼爱就打赏