【问题标题】:m piles of coin with different value, you are only allowed to get coins from the top. Assuming you can take n coins home, what is the max value?m 堆不同价值的硬币,您只能从顶部获得硬币。假设你可以带 n 个硬币回家,最大值是多少?
【发布时间】:2016-12-11 10:53:38
【问题描述】:

问题如上所述。基本上,输入是vector<stack<int>>& piles 和n,输出是任何堆中所有n 硬币的最大值。

我能想到的唯一解决方案是对每一堆使用回溯,即选择piles[0]i硬币,然后递归调用piles[1...m-1]和n - i上的函数。并记录所有可能组合的最大值。我觉得这可以通过动态编程来解决,但是,由于 n 的约束,我很难建立一个 dp 方程。

有比回溯更好的解决方案吗?

【问题讨论】:

  • 问题来源是什么?还有m&n&coin的价值限制是多少?

标签: c++ algorithm dynamic-programming backtracking


【解决方案1】:

有 m 堆。每堆 p 提供 n+1 个贡献 (label, gain, cost): 因为我从 0 到 n 有("pile {p}, {i} taken", sum of top i values, i)。

成本总和必须等于(或小于负数时)n,增益最大。

其余的取决于算法:是否按((double)gain)/cost 或其他方式降序排序。

【讨论】:

    【解决方案2】:

    这绝对是 nHr 组合。 我会使用这样的代码.. p = 堆数,n = 取的硬币。 calc_sum 是记录最大值的函数。

    nHr h(p, n);
    while(h.next()) {
        for(int i=0; i<h.size(); i++) take_coins_from_a_pile(h[i]);
        calc_sum();
    }
    

    这是我自己的 nHr 图书馆。

    #pragma once
    #include <exception>
    
    class NRexception : public std::exception
    {
    public:
        virtual const char* what() const throw() {
            return "Combination : N, R should be positive integer!!";
        }
    };
    
    class Combination
    {
    public:
        Combination(int n, int r);
        virtual ~Combination() { delete [] ar;}
        int& operator[](unsigned i) {return ar[i];}
        bool next();
        int size() {return r;}
        static int factorial(int n);
    
    protected:
        int* ar;
        int n, r;
    };
    
    class nCr : public Combination
    {
    public: 
        nCr(int n, int r);
        bool next();
        int count() const;
    };
    
    class nTr : public Combination
    {
    public:
        nTr(int n, int r);
        bool next();
        int count() const;
    };
    
    class nHr : public nTr
    {
    public:
        nHr(int n, int r) : nTr(n,r) {}
        bool next();
        int count() const;
    };
    
    class nPr : public Combination
    {
    public:
        nPr(int n, int r);
        virtual ~nPr() {delete [] on;}
        bool next();
        void rewind();
        int count() const;
    
    private:
        bool* on;
        void inc_ar(int i);
    };
    
    #include "combi.h"
    #include <set>
    #include<cmath>
    
    Combination::Combination(int n, int r)
    {
        //if(n < 1 || r < 1) throw NRexception();
        ar = new int[r];
        this->n = n;
        this->r = r;
    }
    
    int Combination::factorial(int n) 
    {
        return n == 1 ? n : n * factorial(n-1);
    }
    
    int nPr::count() const
    {
        return factorial(n)/factorial(n-r);
    }
    
    int nCr::count() const
    {
        return factorial(n)/factorial(n-r)/factorial(r);
    }
    
    int nTr::count() const
    {
        return pow(n, r);
    }
    
    int nHr::count() const
    {
        return factorial(n+r-1)/factorial(n-1)/factorial(r);
    }
    
    nCr::nCr(int n, int r) : Combination(n, r)
    {
        if(r == 0) return;
        for(int i=0; i<r-1; i++) ar[i] = i + 1;
        ar[r-1] = r-1;
    }
    
    nTr::nTr(int n, int r) : Combination(n, r)
    {
        for(int i=0; i<r-1; i++) ar[i] = 1;
        ar[r-1] = 0;
    }
    
    bool nCr::next()
    {
        if(r == 0) return false;
        ar[r-1]++;
        int i = r-1;
        while(ar[i] == n-r+2+i) {
            if(--i == -1) return false;
            ar[i]++;
        }
        while(i < r-1) ar[i+1] = ar[i++] + 1;
        return true;
    }
    
    bool nTr::next()
    {
        ar[r-1]++;
        int i = r-1;
        while(ar[i] == n+1) {
            ar[i] = 1;
            if(--i == -1) return false;
            ar[i]++;
        }
        return true;
    }
    
    bool nHr::next()
    {
        ar[r-1]++;
        int i = r-1;
        while(ar[i] == n+1) {
            if(--i == -1) return false;
            ar[i]++;
        }
        while(i < r-1) ar[i+1] = ar[i++];
        return true;
    }
    
    nPr::nPr(int n, int r) : Combination(n, r)
    {
        on = new bool[n+2];
        for(int i=0; i<n+2; i++) on[i] = false;
        for(int i=0; i<r; i++) {
            ar[i] = i + 1;
            on[i] = true;
        }
        ar[r-1] = 0;
    }
    
    void nPr::rewind()
    {
        for(int i=0; i<r; i++) {
            ar[i] = i + 1;
            on[i] = true;
        }
        ar[r-1] = 0;
    }
    
    bool nPr::next()
    {   
        inc_ar(r-1);
    
        int i = r-1;
        while(ar[i] == n+1) {
            if(--i == -1) return false;
            inc_ar(i);
        }
        while(i < r-1) {
            ar[++i] = 0;
            inc_ar(i);
        }
        return true;
    }
    
    void nPr::inc_ar(int i)
    {
        on[ar[i]] = false;
        while(on[++ar[i]]);
        if(ar[i] != n+1) on[ar[i]] = true;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-01-24
      • 2020-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-21
      • 2020-05-09
      • 2017-01-10
      • 1970-01-01
      相关资源
      最近更新 更多