m堆不同价值的硬币,你只能从顶部获得硬币.假设你能把n个硬币带回家,最大值是多少

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?

本文关键字:硬币 假设 带回家 多少 最大值 顶部      更新时间:2023-10-16

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

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

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

共有m个桩。每个桩p提供n+1个贡献(label, gain, cost):对于从0到n的i具有CCD_ 10。

成本之和必须等于(或小于负数)n,获得最大值。

剩下的取决于算法:是否按((double)gain)/cost降序排序。

这绝对是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;
}