我想生成X个随机数,每个都来自<0; Y>
区间(给定Y
作为每个数字的最大值),但是这些数字的总和必须等于{ {1}}。
实施例:
5个Randoms数字,每个最大值6和总和必须等于14,例如:Z
是否已经有可以做类似的C / C ++功能?
就我个人而言,我无法想出一些丑陋的if-else-constucts。
答案 0 :(得分:2)
由于您不需要生成的序列是统一的,因此这可能是可能的解决方案之一:
#include <iostream>
#include <vector>
#include <cstdlib>
int irand(int min, int max) {
return ((double)rand() / ((double)RAND_MAX + 1.0)) * (max - min + 1) + min;
}
int main()
{
int COUNT = 5, // X
MAX_VAL = 6, // Y
MAX_SUM = 14; // Z
std::vector<int> buckets(COUNT, 0);
srand(time(0));
int remaining = MAX_SUM;
while (remaining > 0)
{
int rndBucketIdx = irand(0, COUNT-1);
if (buckets[rndBucketIdx] == MAX_VAL)
continue; // this bucket is already full
buckets[rndBucketIdx]++;
remaining--;
}
std::cout << "Printing sequence: ";
for (size_t i = 0; i < COUNT; ++i)
std::cout << buckets[i] << ' ';
}
只是简单地将总和除以一堆桶直到它消失为止:)
输出示例:Printing sequence: 4 4 1 0 5
答案 1 :(得分:1)
注意:当问题指定“MAX SUM”参数时,写入此解决方案,意味着小于该金额的总和同样可以接受。现在根据OP的评论编辑了这个问题,他们认为累积金额实际上必须达到该目标。我不要更新这个答案,但显然它可以在递归的最后一级轻易丢弃较小的总数。
此解决方案执行vector<vector<int>>
的一次性填充,其中所有可能的数字组合解决了输入条件,然后每次需要新的解决方案时,它会随机选择其中一个并将数字混洗到随机顺序(从而选择组合的排列)。
这有点重 - 可能不适合你在我开始编写后提到的实际用途;-P - 但它会产生 偶数加权分布 ,你可以轻松地做一些事情,比如保证在返回所有其他组合之前不会再次返回组合(在组合中使用支持的混合索引向量)。
#include <iostream>
#include <vector>
#include <algorithm>
using std::min;
using std::max;
using std::vector;
// print solutions...
void p(const vector<vector<int>>& vvi)
{
for (int i = 0; i < vvi.size(); ++i)
{
for (int j = 0; j < vvi[i].size(); ++j)
std::cout << vvi[i][j] << ' ';
std::cout << '\n';
}
}
// populate results with solutions...
void f(vector<vector<int>>& results, int n, int max_each, int max_total)
{
if (n == 0) return;
if (results.size() == 0)
{
for (int i = 0; i <= min(max_each, max_total); ++i)
results.push_back(vector<int>(2, i));
f(results, n - 1, max_each, max_total);
return;
}
vector<vector<int>> new_results;
for (int r = 0; r < results.size(); ++r)
{
int previous = *(results[r].rbegin() + 1);
int current_total = results[r].back();
int remaining = max_total - current_total;
for (int i = 0; i <= min(previous,min(max_each, remaining)); ++i)
{
vector<int> v = results[r];
v.back() = i;
v.push_back(current_total + i);
new_results.push_back(v);
}
}
results = new_results;
f(results, n - 1, max_each, max_total);
}
const vector<int>& once(vector<vector<int>>& solutions)
{
int which = std::rand() % solutions.size();
vector<int>& v = solutions[which];
std::random_shuffle(v.begin(), v.end() - 1);
return v;
}
int main()
{
vector<vector<int>> solutions;
f(solutions, 5, 6, 14);
std::cout << "All solution combinations...\n";
p(solutions);
std::cout << "------------------\n";
std::cout << "A few sample permutations...\n";
for (int n = 1; n <= 100; ++n)
{
const vector<int>& o = once(solutions);
for (int i = 0; i < o.size() - 1; ++i)
std::cout << o[i] << ' ';
std::cout << '\n';
}
}
答案 2 :(得分:0)
#include<iostream>
#include <cstdlib> //rand ()
using namespace std;
void main()
{
int random ,x=5;
int max , totalMax=0 , sum=0;
cout<<"Enter the total maximum number : ";
cin>>totalMax;
cout<<"Enter the maximum number: ";
cin>>max;
srand(0);
for( int i=0; i<x ; i++)
{
random=rand()%max+1; //range from 0 to max
sum+=random;
if(sum>=totalMax)
{
sum-=random;
i--;
}
else
cout<<random<<' ';
}
cout<<endl<<"Reached total maximum number "<<totalMax<<endl;
}
我写了这个简单的代码
我用totalMax = 14和max = 3测试了它,它和我一起工作
希望这是你要求的
答案 3 :(得分:0)
LiHo的回答与我的第二个建议非常相似,所以我会离开,但这是第一个例子。它可能会得到改善,但它不应该有任何悲剧性的错误。 Here's a live sample.
#include <algorithm>
#include <array>
#include <random>
std::random_device rd;
std::mt19937 gen(rd());
constexpr int MAX = 14;
constexpr int LINES = 5;
int sum{};
int maxNum = 6;
int minNum{};
std::array<int, LINES> nums;
for (int i = 0; i < LINES; ++i) {
maxNum = std::min(maxNum, MAX - sum);
minNum = std::min(maxNum, std::max(minNum, MAX - maxNum * (LINES - i)));
std::uniform_int_distribution<> dist(minNum, maxNum);
int num = dist(gen);
nums[i] = num;
sum += num;
}
std::shuffle(std::begin(nums), std::end(nums), gen);
每次创建这个ditribution可能会减慢它(我不知道),但是范围必须在构造函数中,并且我不能说这些数字的分布有多好。但是,逻辑非常简单。除此之外,它使用漂亮,闪亮的C ++ 11 <random>
标题。
我们只是确保没有剩余的数字超过MAX
(14)并且到达时达到MAX
。 minNum
是奇怪的部分,这是由于它的进展。它从零开始并根据需要向上移动(std::max
的第二部分是在确定如果我们为其余部分获得6分时需要什么),但我们不能让它超过maxNum
。我愿意采用一种更简单的方法来计算minNum
是否存在。