当前位置:   article > 正文

动态规划入门第3课,经典DP问题2 --- 背包问题_第1题 方案数 查看测评数据信息 给你n个整数,每个数可选或不选,要求选一些数,使它

第1题 方案数 查看测评数据信息 给你n个整数,每个数可选或不选,要求选一些数,使它

 

  • 练习1
第1题     方案数 查看测评数据信息

给你n个整数,每个数可选或不选,要求选一些数,使它们的和为S,问有多少种方案?

输入格式

  第一行:2个整数n和s,范围都在[1, 100]。

  第二行:n个整数,每个数范围在[-100, 100]。

输出格式

输出方案数。(答案不超过2^63)

输入/输出例子1

输入:

6 10

3 4 7 8 -1 2 

输出:

  4

样例解释:

  3+7, 3+8-1, 4+7-1, 8+2

样例解释

代码奉上

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n,s,d[10011];
  4. long long f[10001];
  5. int main(){
  6. cin>>n>>s;
  7. for(int i = 1;i <= n;i++){
  8. cin>>d[i];
  9. }
  10. sort(d+1,d+n+1);
  11. int m=n+1;
  12. for(int i = 1;i <= n;i++){
  13. if(d[i]>= 0){
  14. m = i;
  15. break;
  16. }
  17. }
  18. f[0] = 1;
  19. for(int i = m;i <= n;i++){
  20. for(int j = 10000;j >= 0;j--){
  21. if(f[j] != 0&&(j+d[i]<= 10000)){
  22. f[j+d[i]]+=f[j];
  23. }
  24. }
  25. }
  26. for(int i = 1;i < m;i++){
  27. for(int j = 0;j <=10000;j++){
  28. if(f[j] != 0&&(j+d[i]>= 0)){
  29. f[j+d[i]]+=f[j];
  30. }
  31. }
  32. }
  33. cout<<f[s];
  34. return 0;
  35. }

第2题     差距最小 查看测评数据信息

给你n个正整数,要求你分成2堆,使它们各自的和尽量相同。问2堆的差距最小是多少?

输入格式

 第一行:1个整数n,范围都在[1, 1000]。

  第二行:n个整数,每个数范围在[1, 100]。

输出格式

输出最小差距。

输入/输出例子1

输入:

  6

  3 4 7 8 1 2 

输出:

  1

样例解释:

  13=3+7+1+2

  12=4+8

样例解释

代码:

  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. using namespace std;
  5. const int MAX_N = 1005;
  6. const int MAX_SUM = 50005;
  7. int main() {
  8. int n;
  9. cin >> n;
  10. vector<int> nums(n);
  11. int sum = 0;
  12. for (int i = 0; i < n; i++) {
  13. cin >> nums[i];
  14. sum += nums[i];
  15. }
  16. int half_sum = sum / 2;
  17. vector<bool> dp(MAX_SUM, false);
  18. dp[0] = true;
  19. for (int i = 0; i < n; i++) {
  20. for (int j = half_sum; j >= nums[i]; j--) {
  21. if (dp[j - nums[i]]) {
  22. dp[j] = true;
  23. }
  24. }
  25. }
  26. int min_diff = sum;
  27. for (int j = half_sum; j >= 0; j--) {
  28. if (dp[j]) {
  29. min_diff = sum - 2 * j;
  30. break;
  31. }
  32. }
  33. cout << min_diff << endl;
  34. return 0;
  35. }

第3题     打印方案 查看测评数据信息

给你n个正整数,每个数可选或不选,要求选一些数,使它们的和为S,输出任意一种方案。

输入格式

  第一行:2个整数n和s,范围都在[1, 10000]。

  第二行:n个整数,每个数范围在[1, 1000]。

输出格式

输出任意一种方案。如果没有方案,输出-1。

输入/输出例子1

输入:

 6 110

  30 50 100 70 30 40

 

输出:

  30 50 30

样例解释:

  或者 70 40也可以。

样例解释

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. long long n,a,s;
  4. long long fa[1000005],b[1000005];
  5. int main()
  6. {
  7. cin>>n>>s;
  8. b[0]=1;
  9. for(int i=1;i<=n;i++){
  10. cin>>a;
  11. if(a>s)continue;
  12. for(int j=s;j>=0;j--)
  13. {
  14. if(b[j]!=0&&!fa[j+a])
  15. {
  16. b[j+a]++;
  17. fa[j+a]=a;
  18. }
  19. }
  20. }
  21. if(b[s]==0)
  22. {
  23. cout<<-1;
  24. return 0;
  25. }
  26. while(s!=0)
  27. {
  28. cout<<fa[s]<<" ";
  29. s-=fa[s];
  30. }
  31. return 0;
  32. }

 

  • 练习2
第1题     储钱罐 查看测评数据信息

给出储钱罐的重量,每种钱对应的重量和价值,求出储钱罐内至少有多少钱?                    

输入格式

  第一行为一个正整数T,表示T(T<=5)组测试数据。

每组数据:

第一行为两个正整数E,F(1<=E<=F<=10000),表示空的储钱罐的重量和装了钱后的重量。

第二行为一个正整数N(1<=N<=500),表示钱的种类数。

接着的N行每一行有两个正整数P,W(1<=P<=50000, 1<=W<=10000),表示钱的价值与重量。

输出格式

每组测试数据一行一个句子“The minimum amount of money in the piggy-bank is X.”X为至少有多少钱,如果无解,则输出“This is impossible.”(注意有英文句号)

 

输入/输出例子1

输入:

3

10 110

2

1 1

30 50

10 110

2

1 1

50 30

1 6

2

10 3

20 4

输出:

The minimum amount of money in the piggy-bank is 60.

The minimum amount of money in the piggy-bank is 100.

This is impossible.

样例解释

代码

  1. #include <iostream>
  2. #include <vector>
  3. #include <limits>
  4. int findMinimumAmount(int E, int F, int N, std::vector<std::pair<int, int> >& coins) {
  5. std::vector<int> dp(F + 1, std::numeric_limits<int>::max());
  6. dp[0] = 0;
  7. for (int j = 0; j < N; j++) {
  8. for (int i = 1; i <= F; i++) {
  9. if (i >= coins[j].second && dp[i - coins[j].second] != std::numeric_limits<int>::max()) {
  10. dp[i] = std::min(dp[i], dp[i - coins[j].second] + coins[j].first);
  11. }
  12. }
  13. }
  14. return (dp[F-E] != std::numeric_limits<int>::max()) ? dp[F-E] : -1;
  15. }
  16. int main() {
  17. int T;
  18. std::cin >> T;
  19. while (T--) {
  20. int E, F;
  21. std::cin >> E >> F;
  22. int N;
  23. std::cin >> N;
  24. std::vector<std::pair<int, int> > coins(N);
  25. for (int i = 0; i < N; i++) {
  26. std::cin >> coins[i].first >> coins[i].second;
  27. }
  28. int result = findMinimumAmount(E, F, N, coins);
  29. if (result != -1) {
  30. std::cout << "The minimum amount of money in the piggy-bank is " << result << "." << std::endl;
  31. } else {
  32. std::cout << "This is impossible." << std::endl;
  33. }
  34. }
  35. return 0;
  36. }

 

  • 练习3 
第1题     多重背包 查看测评数据信息

给出N种钱币的面值和每种钱币的个数,问要凑出M的钱最少要用多少枚钱币?

例如:N=4,M=40,钱币面值分别为:3,6,8,9 , 个数分别是:10,10,2,1。

答案为:6。

输入格式

  第一行:2个整数N和M,N范围在[1,50],M范围在[1,1000000]。

第二行:N个整数表示每种钱币的面值,每个数范围在[1,100]。

第三行:N个整数表示每种钱币的数量,每个数范围在[1,100000]。

输出格式

  输出最少钱币数。  输出最少钱币数。如果没有方案,输出-1。

输入/输出例子1

输入:

  2 100

  5 8

  20 6

输出:

  17

样例解释

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int N,M,d[510],c[510],ans = 0;
  4. int nn,dd[10000],cc[10000];
  5. int f[10000006];
  6. int main(){
  7. cin>>N>>M;
  8. for(int i = 1;i <= N;i++){
  9. cin>>d[i];
  10. }
  11. for(int i = 1;i <= N;i++){
  12. cin>>c[i];
  13. if(c[i]>M/d[i]){
  14. c[i] = M/d[i];
  15. }
  16. }
  17. nn = 0;
  18. for(int i = 1;i <= N;i++){
  19. int x = c[i];
  20. for(int p2 = 1;x > p2;p2*=2){
  21. dd[++nn] = p2*d[i];
  22. cc[nn] = p2;
  23. x -= p2;
  24. }
  25. if(x > 0){
  26. dd[++nn] = x*d[i];
  27. cc[nn] = x;
  28. }
  29. }
  30. f[0] = 1;
  31. for(int i = 1;i <= nn;i++){
  32. for(int j = M-dd[i];j >= 0;j--){
  33. if(f[j]>0){
  34. if(f[j+dd[i]] == 0|| f[j+dd[i]]>f[j]+cc[i]){
  35. f[j+dd[i]] = f[j]+cc[i];
  36. }
  37. }
  38. }
  39. }
  40. ans = f[M]-1;
  41. cout<<ans;
  42. return 0;
  43. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/689965
推荐阅读
相关标签
  

闽ICP备14008679号