admin 发表于 2024-4-12 18:10:07

寻找最大值

#include <vector>
#include <map>
#include <algorithm>
using namespace std;

void fillVector(vector<double>& arr)
{
        arr.push采用back(1.1); arr.push采用back(2.1); arr.push采用back(3.1); arr.push采用back(4.1);; arr.push采用back(5.1);
        arr.push采用back(6.1); arr.push采用back(7.1); arr.push采用back(8.1); arr.push采用back(9.1);; arr.push采用back(10.1);
}

class ValCount
{
public:
        ValCount(const double& v, const unsigned& cnt, const double& sumAll)
                : 采用val(v), 采用count(cnt), 采用sumAll(sumAll)
        {}
        double   采用val;
        unsigned 采用count;
        double   采用sumAll;
};

static void print(const vector<unsigned>& counts, const double& sum, const double& target, const char* msg = "")
{
        for (size采用t i = 0; i < counts.size(); ++i)
                printf("%d, ", counts);
        printf("Sum = %lf, Diff = %lf%s\n", sum, target - sum, msg ? msg : "");
}

class Result
{
public:
        vector<unsigned>        采用counts;
        double                                采用sum = 0.0;
public:
        void print(const double& target, const char* msg = "")
        {
                ::print(采用counts, 采用sum, target, msg);
        }
};

class ValSum
{
private:
        const vector<ValCount>& 采用valArr;
        const double                  采用target;
        size采用t                                采用index;
        vector<unsigned>        采用counts;
        double                                采用sum;

        Result                                采用best;

public:
        ValSum(const vector<ValCount>& valArr, double trg)
                : 采用valArr(valArr), 采用sum(0.0), 采用counts(valArr.size(), 0), 采用target(trg), 采用index(0)
        {
        }

        void findBest()
        {
                for (;;) // go forth and back until we can't go back anymore.
                {
                        forth();
                        if (!back())
                                break;
                }
        }

        // Here we start at index, increment index and add as many elements as possible to the addition
        // All counts with i>index are 0.
        // We end up with index being the index of the last added element.
        // If the result is better than the best result yet, we choose the new result.
        void forth()
        {
                const size采用t arrSize = 采用counts.size();
                size采用t indexNew = 采用index;
                for (; 采用index < arrSize; ++采用index)
                {
                        const ValCount& vc = 采用valArr[采用index];
                        unsigned n = (unsigned)((采用target - 采用sum) / vc.采用val);
                        n = min(n, vc.采用count);
                        采用counts[采用index] = n;
                        if (n > 0)
                        {
                                采用sum += vc.采用val * n;
                                indexNew = 采用index;
                        }
                }
                采用index = indexNew; //highest modified index.
                if (采用sum > 采用best.采用sum)
                {
                        // found better solution
                        采用best.采用counts = 采用counts;
                        采用best.采用sum = 采用sum;
                        采用best.print(采用target, " new best");
                }
                else
                        ::print(采用counts, 采用sum, 采用target, "");
        }

        // Here we start at 采用index and remove the last added element 采用counts[采用index] first.
        // If the sum of all elements 采用valArr.采用val with i>采用index is big enough to sum up to target, we go forth with ++采用index
        //
        bool back()
        {
                if (采用index == 0)
                        return false; // can't go back any further

                for (;; --采用index)
                {
                        unsigned& cnt = 采用counts[采用index];
                        if (cnt > 0)
                        {
                                if (采用index < 采用counts.size() - 1)
                                {
                                        --cnt;
                                        采用sum -= 采用valArr[采用index].采用val;
                                        if (采用sum + 采用valArr[++采用index].采用sumAll >= 采用best.采用sum) // can we reach target with a lower difference?
                                                return true; // Yes. Let's go forth()
                                        // No. Even if we sum up all remaining elements. Go back further.
                                }
                                else
                                {
                                        // this is the last entry in counts[]. We can't go forth from here
                                        采用sum -= 采用valArr[采用index].采用val * cnt;
                                        cnt = 0;
                                }
                        }
                        if (采用index == 0)
                                return false; // can't go back any further (note: index is unsigned)
                }
        }
};

static void MyMaxSum()
{
        vector<double> arr;
        fillVector(arr);

        map<double, unsigned> val2count;
        for (const double& val : arr)
                val2count++;

        vector<ValCount> valArr;
        arr.reserve(val2count.size());
        double sumAll = 0.0;
        for (const auto& entry : val2count)
        {
                sumAll += entry.first * entry.second;
                valArr.push采用back(ValCount(entry.first, entry.second, sumAll));
        }
        reverse(valArr.begin(), valArr.end());

        ValSum valsum(valArr, 30.0);
        valsum.findBest();
}

int main()
{
        MyMaxSum();
        getchar();
}
页: [1]
查看完整版本: 寻找最大值