使用背包解决硬币变化。参考:另一个背包Hackerrank CodeAgon

时间:2015-09-04 07:11:03

标签: dynamic-programming knapsack-problem

问题相当简单直接。但是我不能完全使用dp背包式解决它。我有解决方案,但由于这里每个面额的硬币数量有限(在这个问题中)它会产生问题。我想得到一个可以用来实现背包的2d复发。 我的实际解决方案运行正常如下:

#include<iostream> 
using namespace std ; 
int main ()
{ int flag ;
  int N,i ; 
  int sum ; 
  int counter ; 
  while (cin >> N >>sum )
  {  
    counter = 0; 
    flag= 0 ;
    int count =0; 
    for( i = N ; i>=1;i--){
      count += i ;
      counter++;
      if (count >sum){
      count-=i ;
      counter -- ;  
      }
      if(count == sum){
      flag = 1 ;
      break ; 
      }
      }
 if (flag==1)
 cout << counter<<"\n" ;
 else cout <<-1<<"\n" ;
}
return 0 ;
}

1 个答案:

答案 0 :(得分:0)

问题不需要动态编程解决方案,因为约束非常高。简单的贪婪方法可以正常工作。

该算法的工作原理如下:

  1. 如果从1到n的所有值的总和小于m,那么你就不能支付m币,因为即使在使用了所有n个硬币之后,你还有剩余的钱需要支付。
  2. 如果从1到n的所有值的总和大于或等于m,那么你肯定可以支付,因为你有足够的硬币。
  3. 由于你必须尽量减少给予的硬币数量,你要连续选择具有最大值的硬币,直到你的m变为零,你只需跟踪你所选择的硬币数量。
  4. 以下是实现上述算法的代码

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        int n, m;
        cin >> n >> m;
        if (m > (n * (n + 1) / 2)) {
            //if sum of all coins form 1 to n is less than m
            cout << "-1";
        } else {
            int cnt = 0;
            while (m != 0) {
                if (n >= m) {
                    m = 0;
                } else {
                    m -= n;
                    --n;
                }
                ++cnt;
            }
            cout << cnt;
        }
        return 0;
    }