C++ m堆不同价值的硬币,您只能从顶部获得硬币。假设你可以带n枚硬币回家,最大值是多少?
问题如上所述。基本上,输入是C++ m堆不同价值的硬币,您只能从顶部获得硬币。假设你可以带n枚硬币回家,最大值是多少?,c++,algorithm,dynamic-programming,backtracking,C++,Algorithm,Dynamic Programming,Backtracking,问题如上所述。基本上,输入是vector&piles和n,输出是任何一堆n硬币的最大值 我能想到的唯一解决方案是对每一堆硬币使用回溯,即选择piles[0]Icoins,然后递归调用piles[1…m-1]和n-I上的函数。并记录所有可能组合的最大值。我觉得这可以通过动态规划来解决,但是,由于约束n,我很难建立dp方程 有比回溯更好的解决方案吗?有m个桩。每个桩p提供的n+1贡献为 (标签、收益、成本): 对于从0到n的i,有({p},{i}take),顶部i值之和,i) 成本之和必须等于(或小
vector&piles
和n
,输出是任何一堆n
硬币的最大值
我能想到的唯一解决方案是对每一堆硬币使用回溯,即选择piles[0]
I
coins,然后递归调用piles[1…m-1]
和n-I
上的函数。并记录所有可能组合的最大值。我觉得这可以通过动态规划来解决,但是,由于约束n
,我很难建立dp方程
有比回溯更好的解决方案吗?有m个桩。每个桩p提供的n+1贡献为
(标签、收益、成本)
:
对于从0到n的i,有({p},{i}take),顶部i值之和,i)
成本之和必须等于(或小于负数时)n,增益最大
剩下的取决于算法:是否按
((双)增益)/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-h(p,n);
while(h.next()){
对于(int i=0;in=n;
这个->r=r;
}
整数组合::阶乘(整数n)
{
返回n==1?n:n*阶乘(n-1);
}
int nPr::count()常量
{
返回阶乘(n)/阶乘(n-r);
}
int nCr::count()常量
{
返回阶乘(n)/阶乘(n-r)/阶乘(r);
}
int nTr::count()常量
{
返回功率(n,r);
}
int nHr::count()常量
{
收益阶乘(n+r-1)/阶乘(n-1)/阶乘(r);
}
nCr::nCr(整数n,整数r):组合(n,r)
{
如果(r==0)返回;
对于(int i=0;i)问题的根源是什么?m&n&coins的价值限制是什么?
#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;
}