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?
问题如上所述。基本上,输入是vector<stack<int>>& piles
和n
,输出是来自任何堆的所有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;
}
相关文章:
- 最小硬币更换问题(自上而下方法)
- 如何在硬币兑换问题中找到硬币的数量
- 为什么 GCC 不能假设 std::vector::size 在这个循环中不会改变?
- 这个方程 x + y = x & y + x |y 成立(假设 x, y > 0)?
- 硬币兑换:找到多种方法来重现给定的总和
- 假设声明中某些上下文中需要的名称查找规则是什么
- 在 c++ 中模拟抛硬币时,模数如何工作?
- 用给定面值的最小硬币数量计价金额.贪婪的问题
- 抛硬币计数游戏C++数据结构!.
- 如何在硬币兑换中添加记忆
- 使用OpenCV计数硬币
- 围绕"?"使用的混淆,因为没有假设值
- 假设 a 是双倍的,2.0*a 比 2*a 快吗?
- 假设CPU的解码指令
- 如何缩短此C++代码?(硬币兑换计算器)
- 如何使用C++中不是文字的变量在数字中显示单引号和两个引号?假设 6'2" 英尺
- 假设传递给 OpenGL 的结构数组的内存布局存在潜在错误
- 假设相同的 lambda 表达式具有不同的类型是否安全?
- 本征是否假设混叠?
- m堆不同价值的硬币,你只能从顶部获得硬币.假设你能把n个硬币带回家,最大值是多少