请告诉我如何找到ICPC编程大赛的解决方案

时间:2020-02-01 09:14:42

标签: algorithm

几天来,我一直在寻找解决以下问题的方法。

坚果

今天,塞玛和尤拉参加了一场奥林匹克运动会的闭幕式。假期餐桌上有n盘坚果。第i个板中装有AI螺母。

Sema可以在一分钟内选择一些盘子和一定数量的x,然后从每个选定的盘子中拿起恰好x个坚果(当然,每个选定的盘子应该至少有x个坚果)。

确定所有螺母在Sema口袋中的最小停留时间是多少。

输入 第一行包含一个整数n(1≤n≤50)-带螺母的板数。

第二行包含n个整数a1,a2,...,an(1≤ai≤50)-第i个板中的螺母数。

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

输入示例#1

4 7 4 11 7

输出示例1

2

以下是任务的链接:https://www.e-olymp.com/en/problems/8769在这里您可以检查解决方案。

如果有人至少告诉我寻找解决方案的方法,我将不胜感激。谢谢。

我最好的解决方案是

#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%的测试

#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;
}

56%的测试

#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;
}

57%的测试

1 个答案:

答案 0 :(得分:1)

尽力而为并被接受,尽管我怀疑我的解决方案是否是预期的方法。 有两个发现对我有帮助:

  • 没有选择一次以上的数字。
  • 在所有情况下,
  • 6分钟就足够了。 (对于从1到50的所有数字k,存在{1,2,4,8,11,24}的子集S,使得S中的数字加起来等于k)。

因此,我们可以用最多5个元素测试{1,...,50}的所有子集,并且如果我们找不到少于6个元素的解决方案,则仅输出6。 大约有240万个这样的子集,因此,如果您能够有效地进行此测试,则对它们进行测试是可行的(我使用位操作将其降低到集合中元素数量的线性时间复杂度)。