如何按权重反比将1-100整数分配至多100项的加权列表?
问题描述
我有一个元素带权重的列表,示例如下:
std::vector<float> weights{0.5, 2, 5};
列表长度最少为2项,最多为100项。需要将整数1-100(包含两端)按权重反比分配至该列表,使得权重最低的项获得最大的数值范围。
此处的“权重反比”具体规则示例:
- 输入
weights{2, 1},输出应为类似:2: 1-33 1: 34-100 - 输入
weights{3,1},输出应为类似:3: 1-25 1: 26-100 - 输入
weights{2,1,1},输出应为类似:2: 1-25 1: 26-63 1: 64-100
现有代码无法实现上述反比效果,代码如下:
#include <iostream> #include <vector> #include <iomanip> void distributeNumbers(const std::vector<float>& numbers) { float total = 0; for (float num : numbers) { total += num; } int start = 1; int end = 100; std::cout << "Distributing numbers from 1 to 100 based on proportions:" << std::endl; for (int i = 0; i < numbers.size(); ++i) { float number = numbers[i]; // Calculate the range length for this number double proportion = static_cast<double>(total-number) / total; int rangeLength = static_cast<int>(proportion * 100); // Ensure we don't assign a range of zero length if (i == numbers.size() - 1) { rangeLength = end - start + 1; } int currentEnd = start + rangeLength - 1; std::cout << number << ": " << start << "-" << currentEnd << std::endl; // Update the start for the next number start = currentEnd + 1; } } int main() { std::vector<float> numbers = {9, 4, 3, 11, 7, 19, 3}; // Example input: numbers = {6, 2, 2} distributeNumbers(numbers); return 0; }
问题分析与修正
原代码的核心错误在于比例计算逻辑:(total-number)/total完全不符合“权重反比”的要求。正确的反比逻辑应该是:
- 计算每个权重的反比值:
1/weight_i,权重越小,反比值越大,对应分配的范围越长 - 计算所有反比值的总和
totalInverse - 每个项的分配比例为:
(1/weight_i) / totalInverse,用该比例乘以100得到大致的范围长度 - 处理整数取整的误差,最后一项直接取剩余的所有数值,确保总范围覆盖1-100
修正后的代码如下:
#include <iostream> #include <vector> #include <iomanip> #include <cmath> void distributeNumbers(const std::vector<float>& weights) { double totalInverse = 0.0; // 计算所有权重的反比值总和 for (float w : weights) { totalInverse += 1.0 / w; } int start = 1; const int end = 100; std::cout << "Distributing numbers from 1 to 100 based on inverse weight proportions:" << std::endl; for (size_t i = 0; i < weights.size(); ++i) { float w = weights[i]; // 计算当前项的分配比例 double proportion = (1.0 / w) / totalInverse; // 用round处理取整误差,让结果更贴合比例 int rangeLength = static_cast<int>(std::round(proportion * 100)); // 最后一项直接取剩余所有数值,避免累加误差 if (i == weights.size() - 1) { rangeLength = end - start + 1; } else { // 确保范围长度至少为1,避免极端权重下出现0长度 rangeLength = std::max(rangeLength, 1); // 同时避免超过剩余可用数值 rangeLength = std::min(rangeLength, end - start + 1); } int currentEnd = start + rangeLength - 1; std::cout << w << ": " << start << "-" << currentEnd << std::endl; start = currentEnd + 1; } } int main() { // 测试示例1:weights{2,1} std::vector<float> test1 = {2, 1}; std::cout << "Test 1 input: {2, 1}" << std::endl; distributeNumbers(test1); std::cout << std::endl; // 测试示例2:weights{3,1} std::vector<float> test2 = {3, 1}; std::cout << "Test 2 input: {3, 1}" << std::endl; distributeNumbers(test2); std::cout << std::endl; // 测试示例3:weights{2,1,1} std::vector<float> test3 = {2, 1, 1}; std::cout << "Test 3 input: {2, 1, 1}" << std::endl; distributeNumbers(test3); std::cout << std::endl; // 原示例输入 std::vector<float> numbers = {9, 4, 3, 11, 7, 19, 3}; std::cout << "Original input: {9, 4, 3, 11, 7, 19, 3}" << std::endl; distributeNumbers(numbers); return 0; }
代码说明
- 核心逻辑:通过
1/weight转换为反比权重,再计算比例,确保权重越小的项分配到越长的数值范围 - 使用
std::round处理取整,比直接截断更符合比例分配的预期 - 增加了范围长度的边界检查,避免出现0长度或超出剩余数值的情况
- 最后一项强制取剩余所有数值,确保总范围刚好覆盖1-100
内容的提问来源于stack exchange,提问作者D.G. Redd
相关产品推荐
相关产品推荐

