Algorithm 请告诉我如何找到解决ICPC编程竞赛挑战的方法

Algorithm 请告诉我如何找到解决ICPC编程竞赛挑战的方法,algorithm,Algorithm,几天来,我一直在试图找到下面描述的问题的解决方案 坚果 今天,塞马和尤拉出席了一届奥运会的闭幕式。度假桌上有n盘坚果。第i个板包含ai螺母 在一分钟内,Sema可以选择一些盘子和某个数字x,然后从每个选定的盘子中挑选出x个螺母。当然,每个选定的盘子至少应该有x个螺母 确定在最短的几分钟内,所有的坚果都会在Sema的口袋里 输入 第一行包含一个整数n1≤ N≤ 50-带螺母的板的数量 第二行包含n个整数a1、a2、…、和1≤ 人工智能≤ 50-第i个板中的螺母数量 输出 打印一个数字-所需的最小分

几天来,我一直在试图找到下面描述的问题的解决方案

坚果

今天,塞马和尤拉出席了一届奥运会的闭幕式。度假桌上有n盘坚果。第i个板包含ai螺母

在一分钟内,Sema可以选择一些盘子和某个数字x,然后从每个选定的盘子中挑选出x个螺母。当然,每个选定的盘子至少应该有x个螺母

确定在最短的几分钟内,所有的坚果都会在Sema的口袋里

输入 第一行包含一个整数n1≤ N≤ 50-带螺母的板的数量

第二行包含n个整数a1、a2、…、和1≤ 人工智能≤ 50-第i个板中的螺母数量

输出 打印一个数字-所需的最小分钟数

输入示例1

四, 7 4 11 7

输出示例1

二,

这里是任务的链接:您可以在这里查看解决方案

如果有人至少能告诉我该走哪条路才能找到解决方案,我将不胜感激。谢谢

我最好的解决办法是

#include <iostream>
#include <set>
using namespace std;

int main() {
    int n, inputNumber;
    cin>>n;
    set<int> combinations, newCombinations, inputNumbers, existValuesList;

    for(int i = 0; i < n; i++) {
        cin>>inputNumber;
        inputNumbers.insert(inputNumber);
    }

    for(auto inputValue = inputNumbers.begin(); inputValue != inputNumbers.end(); ++inputValue) {
        for(auto combination = combinations.begin(); combination != combinations.end(); ++combination) {
            if (existValuesList.find(*inputValue) != existValuesList.end())
                break;

            newCombinations.insert(*combination + *inputValue);

            if (inputNumbers.find(*combination + *inputValue) != inputNumbers.end()) {
                existValuesList.insert(*combination + *inputValue);
            }
        }

        combinations.insert(*inputValue);
        combinations.insert(newCombinations.begin(), newCombinations.end());
        newCombinations.clear();
    }



    cout<<inputNumbers.size() - existValuesList.size();
    return 0;
}
71%的测试

56%的测试


57%的测试

尝试过并被接受,尽管我怀疑我的解决方案是否是预期的方法。 有两个观察结果帮助了我:

没有一个号码被多次选择。 在所有情况下,6分钟就足够了。对于从1到50的所有数字k,都有一个子集S{1,2,4,8,11,24},这样S中的数字加起来就是k。 因此,我们可以用最多5个元素测试{1,…,50}的所有子集,如果我们找不到少于6个元素的解,只输出6。
有大约240万这样的子集,因此如果您能够有效地进行测试,那么测试它们是可行的。我使用位操作将集合中的元素数降低到线性时间复杂性。

为什么不展示您对该问题的尝试?询问解决方案是离题的。我想问这个问题最好的地方是codegolf.stackexchange.com
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
#include <iterator>


using namespace std;

class Nuts {
public:
    int n;
    set<int> inputNumbers;
    set<int> combinations;
    set<int> elementary;
    set<int> brokenNumbers;
    map<int, set<int>> numbersBreakDown;
    set<int> temporaryCombinations;

    void setN() {
        cin>>n;
    }

    void setInputNumbers() {
        int number;

        for(int i = 0; i < n; i++) {
            cin>>number;
            inputNumbers.insert(number);
        }
    }

    void calculateCombinations() {

        for(int inputNumber : inputNumbers) {
            temporaryCombinations.insert(inputNumber);

            for(int combination : combinations) {
                calculateCombination(inputNumber, combination);
            }

            combinations.insert(temporaryCombinations.begin(), temporaryCombinations.end());
            temporaryCombinations.clear();
        }
    }

    void calculateCombination(int inputNumber, int combination) {
        if (brokenNumbers.find(inputNumber + combination) != brokenNumbers.end()) {
            return;
        }

        if (inputNumbers.find(combination + inputNumber) != inputNumbers.end()) {
            elementary.insert(inputNumber);
            brokenNumbers.insert(inputNumber + combination);
            addNumbersBreakDown(inputNumber, combination, breakDownNumber(combination));
        }

        temporaryCombinations.insert(combination + inputNumber);
    }

    void addNumbersBreakDown(int inputNumber, int combination, set<int> numberBreakDown) {
        set<int> temporaryNumberBreakDown;
        temporaryNumberBreakDown.insert(inputNumber);
        temporaryNumberBreakDown.insert(numberBreakDown.begin(), numberBreakDown.end());
        numbersBreakDown.insert(pair<int, set<int>>(inputNumber + combination, temporaryNumberBreakDown));
    }

    set<int> breakDownNumber(int combination, int count = 5) {
        set<int> numberBreakDown;

        for (int i = 0; i < count; i++) {
            for(int it : inputNumbers) {

                if (it > combination) {
                    continue;
                }

                if (it == combination) {
                    numberBreakDown.insert(combination);
                    return numberBreakDown;
                }

                if (combinations.find(combination - it) != combinations.end()) {
                    combination = combination - it;
                    break;
                }
            }
        }

    }

    void throwOutElementaryBrokenNumbers() {
        for(pair<int, set<int>> num : numbersBreakDown) {
            if (brokenNumbers.find(num.first) == brokenNumbers.end()) {
                continue;
            }

            throwOutElementaryBrokenNumber(num);
        }
    }

    void throwOutElementaryBrokenNumber(pair<int, set<int>> num) {
        int count = 0;

        for(pair<int, set<int>> num1 : numbersBreakDown) {
            if (num1.first != num.first && num1.second.find(num.first) != num1.second.end()) {
                count++;

                if (count > 1) {
                    brokenNumbers.erase(num.first);
                    break;
                }
            }
        }
    }

    void throwOutBrokenNumbers() {
        for(pair<int, set<int>> num : numbersBreakDown) {
            if (brokenNumbers.find(num.first) == brokenNumbers.end()) {
                continue;
            }

            int count = 0;

            for(int number : num.second) {
                if (brokenNumbers.find(number) != brokenNumbers.end()) {
                    count++;

                    if (count > 1) {
                        brokenNumbers.erase(number);
                        break;
                    }
                }
            }
        }
    }

    void getResult() {
        cout<<inputNumbers.size() - brokenNumbers.size();
    }

    void showSet(set<int> mn) {
        for (int i : mn)
            cout<<i<<" ";

        cout<<endl;
    }
};



int main() {
    Nuts task = Nuts();
    task.setN();
    task.setInputNumbers();
    task.calculateCombinations();
    task.throwOutElementaryBrokenNumbers();
    task.throwOutBrokenNumbers();
    task.getResult();

    return 0;
}
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
#include <iterator>


using namespace std;

set<int> getSumSet(set<int> inputValue, int sum, set<int> combinations, set<int> output = {}) {
    set<int> tempComb;
    bool ex = false;

    for(int i = 0; i < 5; i++) {
        for (int val : inputValue) {
            tempComb.insert(val);

            if (sum == val) {
                output.insert(val);
                combinations.clear();
                return output;
            }

            for (int comb : combinations) {

                if (combinations.find(comb - val) != combinations.end()) {
                    output.insert(val);
                    val = comb;
                    ex = true;
                    break;
                }
            }

            if (ex) {
                ex = false;
                break;
            }
        }
    }


    return output;
}

int findLoc(set<int> numbers, int val) {
    int result = 0;

    for (int i : numbers) {
        result++;

        if (i == val) {
            break;
        }
    }

    return numbers.size() - result;
}


int main() {
    int n, inputNumber;
    cin>>n;
    set<int> combinations, inputNumbers, copyInputNumbers, numbersForBreakdown, tempCombinations, elementaryNumbers, test;

    for (int i = 0; i < n; i++) {
        cin>>inputNumber;
        inputNumbers.insert(inputNumber);
        copyInputNumbers.insert(inputNumber);
    }

    elementaryNumbers.insert( *inputNumbers.begin() );

    for (int number : inputNumbers) {
        tempCombinations.insert(number);

        if (copyInputNumbers.find(number) != copyInputNumbers.end()) {
            copyInputNumbers.erase(number);
            elementaryNumbers.insert(number);
        }

        for (int combination : combinations) {

            if (copyInputNumbers.find(combination + number) != copyInputNumbers.end()) {
                set<int> brN = getSumSet(inputNumbers, combination, combinations);
                brN.insert(number);
                copyInputNumbers.erase(combination + number);
                set_difference(brN.begin(), brN.end(), elementaryNumbers.begin(), elementaryNumbers.end(), inserter(test, test.begin()));

                if (findLoc(inputNumbers, combination + number) > test.size() && test.size() < 3) {
                    elementaryNumbers.insert(brN.begin(), brN.end());
                }

                brN.clear();
                test.clear();
            }

            tempCombinations.insert(combination + number);
        }

        combinations.insert(tempCombinations.begin(), tempCombinations.end());
        tempCombinations.clear();
    }

    cout<<elementaryNumbers.size();
    return 0;
}