В настоящее время я работаю над небольшой программой, которая должна находить каждую комбинацию.

Заполните следующие заполнители цифрами в диапазоне от 1 до 9. Каждая цифра появляется только один раз, и сумма уравнения составляет 100.

_ / _ * _ + _ * _ * _ / _ + _ * _ = 100

#include <bits/stdc++.h>
#include <cmath>

using namespace std;

void print(int arr[], int n){
    for (int i = 0; i < n; i++){
        cout << arr[i] << " ";
    }
    cout << endl;
}

void findCombos(int arr[], int n){
    std::sort(arr, arr + n);
    do{
        if((arr[0] / arr[1] * arr[2] + arr[3] * arr[4] * arr[5] / arr[6] + arr[7] * arr[8]) == 100){
            print(arr, n);
        }
    }while(next_permutation(arr, arr + n));
}

int main(){
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int size = sizeof(arr) / sizeof(arr[0]);
    findCombos(arr, size);

    return 0;
} 

Я сгенерировал 900 решений с помощью этого кода. Некоторые из перестановок верны, но некоторые комбинации не вычисляют точно до 100. Мой оператор if правильно сопоставляет операции, но почему отображаются неправильные перестановки? Как расширение, как заставить эту программу работать рекурсивно?

1
Jeff 11 Окт 2021 в 00:46

2 ответа

Лучший ответ

Как уже упоминалось PiedPiper о проблеме целочисленного деления, вы можете просто объявить arr[] как двойное, и это решит проблема.

В качестве расширения вы также можете вычислить перестановки рекурсивным способом. Пожалуйста, проверьте функцию findCombosRecursive(), которая имеет такую ​​же функциональность, что и findCombos(), но создает комбинации рекурсивно.

Рекурсивный алгоритм разбивает arr на две части: уже переставленные элементы и оставшиеся неизмененные элементы. Параметр curr указывает точку поворота между этими двумя частями. Каждый раз мы меняем местами сводный элемент и оставшиеся неизмененные элементы и продвигаем на единицу опорное положение. Как только мы достигли конца массива, мы получаем новую перестановку массива и проверяем, удовлетворяет ли эта перестановка нашему необходимому условию. Не забываем восстанавливать позицию после рекурсивных вызовов. Это гарантирует, что позиция поворота будет заменена только другими оставшимися элементами в одной конструкции перестановки.

Здесь я поделился примером реализации рекурсивного построения решения:

#include <bits/stdc++.h>
#include <cmath>

using namespace std;

void print(double arr[], int n, int sid) {
    cout << "Solution " << sid << ":";
    for (int i = 0; i < n; i++){
        cout << " " << arr[i];
    }
    cout << endl;
}

void findCombosRecursive(double arr[], int size, int curr, int& sid) {
    if (curr == size) {     // base-case of the recursion
        // check whether the current combination satisfy the following condition:
        // "_ / _ * _ + _ * _ * _ / _ + _ * _ = 100"
        if((arr[0] / arr[1] * arr[2] + arr[3] * arr[4] * arr[5] / arr[6] + arr[7] * arr[8]) == 100){
            print(arr, size, sid);
            sid += 1;
        }
    } else {
        for (int i = curr; i < size; i+=1) {
            swap(arr[i], arr[curr]);
            findCombosRecursive(arr, size, curr + 1, sid); // placing next position
            swap(arr[i], arr[curr]);  // restoring
        }
    }
}

void findCombos(double arr[], int n){
    std::sort(arr, arr + n);
    int i = 0;
    do{
        if((arr[0] / arr[1] * arr[2] + arr[3] * arr[4] * arr[5] / arr[6] + arr[7] * arr[8]) == 100){
            print(arr, n, i);
            i += 1;
        }
    } while(next_permutation(arr, arr + n));
}

int main(){
    double arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int size = sizeof(arr) / sizeof(arr[0]);
    int sid = 0;
    findCombosRecursive(arr, size, 0, sid);
    // findCombos(arr, size);

    return 0;
}
0
biqarboy 11 Окт 2021 в 01:22

Вы делите целые числа, что обрезает результат. Если разделить 9 на 2 как целые числа, получится 4, а не 4,5. Это означает, что значение, рассчитанное вашей программой, будет неверным.

3
PiedPiper 10 Окт 2021 в 22:07