Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.86/56: Рейтинг темы: голосов - 56, средняя оценка - 4.86
19 / 19 / 18
Регистрация: 25.08.2014
Сообщений: 186
1

Перестановки без повторений

13.10.2014, 20:50. Показов 10974. Ответов 24
Метки нет (Все метки)

Как из этого кода сделать конфетку — чтобы не выводились повторения?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
 
using namespace std;
 
string s;
 
void gen(unsigned k)
{
    if (k == s.length())
        cout << s << '\n';
    else
        for (unsigned j = k; j < s.length(); j++)
        {
            swap(s[k], s[j]);
            gen(k + 1);
            swap(s[k], s[j]);
        }
}
 
int main()
{
    cin >> s;
    gen(0);
 
    return 0;
}
Добавлено через 18 минут
Да, кстати, в лоб задача не проходит, необходимо что-то хитрее

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <vector>
 
using namespace std;
 
string s;
vector<string> w;
 
void gen(unsigned k)
{
    if (k == s.length())
    {
        bool write = true;
        unsigned i = 0;
        while (write && i < w.size())
        {
            if (w[i] == s)
                write = false;
            i++;
        }
        if (write)
        {
            cout << s << '\n';
            w.push_back(s);
        }
    }
    else
    {
        for (unsigned j = k; j < s.length(); j++)
        {
            swap(s[k], s[j]);
            gen(k + 1);
            swap(s[k], s[j]);
        }
    }
}
 
int main()
{
    cin >> s;
    gen(0);
 
    return 0;
}
Добавлено через 43 минуты
Ну что же вы
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.10.2014, 20:50
Ответы с готовыми решениями:

Перестановки без повторений
Требуется дописать исключение повторений в коде,спасибо. #include &lt;iostream&gt; using namespace...

Перестановки без повторений
привет помогите пожалуйста найти файлик в котором бы были все перестановки из 5 элементов. ...

Выписать все перестановки без повторений
Тему копирую из раздела C#, из-за того что на си народу больше. Есть строка 0,1,2,3,4 и к...

Требуется написать перестановки без повторений
#include &lt;iostream&gt; using namespace std; const int N =11; int n,a,p; void f(int k){ if(k...

24
73 / 59 / 41
Регистрация: 25.06.2014
Сообщений: 360
13.10.2014, 20:54 2
Wiiiiijjj, чтобы зря не гадать, что функция делает?
0
19 / 19 / 18
Регистрация: 25.08.2014
Сообщений: 186
13.10.2014, 21:01  [ТС] 3
Функция генерирует следующую перестановку.
Но делает она это очень медленно.
0
73 / 59 / 41
Регистрация: 25.06.2014
Сообщений: 360
13.10.2014, 21:18 4
Wiiiiijjj, в чем смысл программы-то? Перебрать все варианты положения букв после введенной позиции k?
0
19 / 19 / 18
Регистрация: 25.08.2014
Сообщений: 186
13.10.2014, 21:32  [ТС] 5
Да, ты вводишь строку s, она перебирает и выводит все варианты перестановки символов s без повторений
0
73 / 59 / 41
Регистрация: 25.06.2014
Сообщений: 360
13.10.2014, 22:18 6
Wiiiiijjj, ну у меня есть только идея: в варианте с вектором , вся проблема ,я думаю, в размере вектора , значит, видимо, нужно сделать, чтобы те значения, которые цикл уже прошел и не могут повториться, удалялись из него.

Добавлено через 2 минуты
Wiiiiijjj, т е грубо, слово qwer , прога в начале переберет все варианты, где первая буква q, и тогда можно просто записать сразу в исключения : начинается с "q" - давай до свидания
0
19 / 19 / 18
Регистрация: 25.08.2014
Сообщений: 186
14.10.2014, 19:06  [ТС] 7
Ок, у меня есть еще два варианта — во-первых, если свайпаются два одинаковых элемента, значит вся остальная последовательность уже была, правильно? Вот я пытаюсь флагом это как-то отслеживать, пока что не получается.
И во-вторых — каждый элемент может выводиться на каждой позиции всего лишь определенное количество раз, может быть создать для каждой буквы и позиции счетчик и сравнивать их?
В общем я так решить и не знаю как

Добавлено через 44 минуты
Подскажите же, в каком направлении копать, гугл ничего не выдает познавательного, все одно и тоже — статья с сочетаниями вместо перестановок, вики про перестановки и тема на cyberforem'е о перестановках с повторениями
0
411 / 248 / 118
Регистрация: 26.12.2012
Сообщений: 786
14.10.2014, 19:07 8
Может быть я не правильно понял
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//все варианты перестановок метод next_permutation
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <windows.h>
#include <math.h>
#include <numeric>
#include <functional>
 
using namespace std;
 
void print_char( char elem ) { cout << elem <<" "; }
void (*ppc)( char ) = print_char;
 
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
 vector<char> vec(6);
// последовательность символов: qwerl
vec[0] = 'q'; vec[1] = 'w'; vec[2] = 'e';
vec[3] = 'r'; vec[4] = 'l';
int cnt = 2;
sort( vec.begin(), vec.end() );
for_each( vec.begin(), vec.end(), ppc ); cout << "\t";
// генерируются все перестановки строки "qwerl"
while( next_permutation( vec.begin(), vec.end()))
{
for_each( vec.begin(), vec.end(), ppc );
cout << "\t";
if ( ! ( cnt++ % 6 )) {
cout << "\n";
cnt = 1;
}
}
cout << "\n\n";
 
 
    return 0;
}
1
19 / 19 / 18
Регистрация: 25.08.2014
Сообщений: 186
14.10.2014, 19:29  [ТС] 9
Вот суперфаст решение, но у меня задание именно написать сложный рекурсивный алгоритм, поэтому оно не подходит

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <algorithm>
#include <string>
#include <iostream>
 
using namespace std;
 
int main()
{
    string s;
    cin >> s;
 
    sort(s.begin(), s.end());
    do
    {
        cout << s << '\n';
    } while (next_permutation(s.begin(), s.end()));
 
    return 0;
}
0
Форумчанин
Эксперт CЭксперт С++
8169 / 5017 / 1436
Регистрация: 29.11.2010
Сообщений: 13,455
14.10.2014, 19:30 10
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <algorithm>
#include <iostream>
#include <string>
 
int main()
{
    std::string str;
    std::cin >> str;
    do
    {
        std::cout << str << std::endl;
    } while (std::next_permutation(str.begin(), str.end()));
}
1
19 / 19 / 18
Регистрация: 25.08.2014
Сообщений: 186
14.10.2014, 19:35  [ТС] 11
MrGluck, если перед циклом не отсортировать, то если строка будет, например, cba — ничего не выведется, потому что как только в следующей перестановке элементы упорядочены лексикографически next_permutation возвращает false
0
Форумчанин
Эксперт CЭксперт С++
8169 / 5017 / 1436
Регистрация: 29.11.2010
Сообщений: 13,455
14.10.2014, 19:59 12
Цитата Сообщение от Wiiiiijjj Посмотреть сообщение
MrGluck, если перед циклом не отсортировать, то если строка будет, например, cba — ничего не выведется, потому что как только в следующей перестановке элементы упорядочены лексикографически next_permutation возвращает false
Да, всё так. Упустил при копировании.
Нужная вам самописная функция:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <string>
 
void swap(char &x, char &y)
{
    char tmp = x;
    x = y;
    y = tmp;
}
 
void next_perm(size_t k, std::string &str, const size_t size)
{
    if (k != size)
    {
        for(size_t i = k; i < size; i++)
        {
            swap(str[k], str[i]);
            next_perm(k + 1, str, size); // следующая перестановка
            swap(str[k], str[i]);
        }
    }
    else
        std::cout << str << std::endl;
}
 
int main()
{
    std::string str;
    std::cin >> str;
    next_perm(0, str, str.size());
}
1
19 / 19 / 18
Регистрация: 25.08.2014
Сообщений: 186
14.10.2014, 20:07  [ТС] 13
Да, почти тоже самое в шапке
И это с повторениями, с ними как раз и проблема

Добавлено через 1 минуту
Кстати, может быть ответите на такой вопрос — зачем почти для каждой проги все пишут свой swap с блекджеком? Что не так со стандартным?
0
3414 / 2773 / 751
Регистрация: 25.03.2012
Сообщений: 10,083
Записей в блоге: 1
14.10.2014, 20:11 14
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
 
using namespace std;
 
string s;
 
void gen(unsigned k)
{
    if (k == s.length())
        cout << s << '\n';
    else
        for (unsigned j = k; j < s.length(); j++)
        {
            swap(s[k], s[j]);
            gen(k + 1);
            swap(s[k], s[j]);
        }
}
 
int main()
{
    cin >> s;
    gen(0);
 
    return 0;
}
1)Отсортировать s
2) if (s[k]==s[k-1]) ничего не делать
1
Форумчанин
Эксперт CЭксперт С++
8169 / 5017 / 1436
Регистрация: 29.11.2010
Сообщений: 13,455
14.10.2014, 20:16 15
Оно?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <string>
#include <unordered_set>
 
using uset_str = std::unordered_set<std::string>;
 
void swap(char &x, char &y)
{
    char tmp = x;
    x = y;
    y = tmp;
}
 
void next_perm(size_t k, std::string &str, const size_t size, uset_str &words)
{
    if (k != size)
    {
        for(size_t i = k; i < size; i++)
        {
            swap(str[k], str[i]);
            next_perm(k + 1, str, size, words); // следующая перестановка
            swap(str[k], str[i]);
        }
    }
    else
        words.insert(str);
}
 
int main()
{
    std::string str;
    std::cin >> str;
    uset_str words;
    next_perm(0, str, str.size(), words);
    for (const auto &s : words)
        std::cout << s << std::endl;
}
Цитата Сообщение от Wiiiiijjj Посмотреть сообщение
зачем почти для каждой проги все пишут свой swap с блекджеком? Что не так со стандартным?
В данном случае я явно хотел показать, что заголовочный файл algorithm не используется. Плюс код был взят из программы, где преподаватель явно запрещал его наличие. Аналогично можно спросить зачем писать свою реализацию next_permutation.
0
19 / 19 / 18
Регистрация: 25.08.2014
Сообщений: 186
14.10.2014, 20:33  [ТС] 16
Kuzia domovenok,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <algorithm>
#include <vector>
 
using namespace std;
 
string s;
 
void gen(unsigned k)
{
    if (k == s.length())
        cout << s << '\n';
 
    else
        if (s[k] != s[k-1])
            for (unsigned j = k; j < s.length(); j++)
            {
                swap(s[k], s[j]);
                gen(k + 1);
                swap(s[k], s[j]);
            }
}
 
int main()
{
    cin >> s;
    sort(s.begin(), s.end());
    gen(0);
    
    return 0;
}
Если есть повторения то начинает некоторые ветки пропускать. Сначала думал не выводится только первая отсортированная перестановка, написал костыль, но оказалось нарушается вся рекурсия.

MrGluck, unordered_set опять же можно считать сторонней библиотекой. Наверное в неправильном разделе спрашиваю, потому что суть задачи именно в алгоритме, который можно написать хоть на псевдокоде.
0
3414 / 2773 / 751
Регистрация: 25.03.2012
Сообщений: 10,083
Записей в блоге: 1
14.10.2014, 20:39 17
Лучший ответ Сообщение было отмечено Wiiiiijjj как решение

Решение

Цитата Сообщение от MrGluck Посмотреть сообщение
Оно?
то есть ты предлагаешь мало того что генерировать все перестановки с повторениями, но и затем ещё раз проходить по сету, проверяя наличие повторений....!
Вот до чего доводят шаблонные решения в программировании! Слово "оптимизация" скоро забудется!

Добавлено через 2 минуты
Wiiiiijjj, ой! я думал, ка у тебя это счётчик цикла!
В таком случае
if (s[j]==s[j-1]) ничего не делать
(свои идеи я не проверяю)
1
3 / 3 / 2
Регистрация: 01.07.2013
Сообщений: 89
14.10.2014, 21:05 18
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>
#include <set>
using namespace std; 
int main()
{
    string s;
    cin >> s;
    set<char> set_str;
    for(int i = 0; i < s.length(); i++)
        set_str.insert(s.at(i));
    string new_str;
    set<char>::iterator set_it;
    char *char_ = new char[set_str.size()];
    char_[set_str.size()] = 0;
    int number = 0;
    for(set_it = set_str.begin(); set_it != set_str.end(); set_it++)
    {
        char_[number] = *set_it;
        number++;
    }
    new_str = char_;
    return 0;
}
1
19 / 19 / 18
Регистрация: 25.08.2014
Сообщений: 186
14.10.2014, 21:14  [ТС] 19
topaz23, спасибо, но проблема решена.
Если делать перестановки не из string работать не будет — за пределы массива выйдет на 16 строке.
Ну, я так думаю, проверять не стал.
Еще раз спасибо всем и в частности Kuzia domovenok

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <algorithm>
#include <iostream>
#include <vector>
 
using namespace std;
 
string s;
 
void gen(unsigned k)
{
    if (k == s.length())
        cout << s << '\n';
 
    else
        for (unsigned j = k; j < s.length(); j++)
            if (s[j] != s[j + 1])
            {
                swap(s[k], s[j]);
                gen(k + 1);
                swap(s[k], s[j]);
            }
}
 
int main()
{
    cin >> s;
    sort(s.begin(), s.end());
    gen(0);
 
    return 0;
}
0
Форумчанин
Эксперт CЭксперт С++
8169 / 5017 / 1436
Регистрация: 29.11.2010
Сообщений: 13,455
14.10.2014, 21:26 20
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Вот до чего доводят шаблонные решения в программировании! Слово "оптимизация" скоро забудется!
Преждевременная оптимизация...
В ТЗ ни слова про ограничение по времени работы.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <algorithm>
#include <iostream>
#include <string>
 
int main()
{
    std::string str, last;
    std::cin >> str;
    std::sort(str.begin(), str.end());
    do
    {
        if (str != last)
            std::cout << str << std::endl;
        last = str;
    } while (std::next_permutation(str.begin(), str.end()));
}
Реализацию next_permutation можете взять выше. Суть алгоритма укладывается в несколько строк.

Добавлено через 1 минуту
Цитата Сообщение от Wiiiiijjj Посмотреть сообщение
MrGluck, unordered_set опять же можно считать сторонней библиотекой.
Это всё стандартная библиотека

Добавлено через 2 минуты
Wiiiiijjj, протестируйте на своём варианте baab
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.10.2014, 21:26

Сгенерировать всевозможные перестановки N чисел без повторений
Условие задачи: Сгенерировать всевозможные перестановки N чисел без повторений. (Использовать...

Перестановки без i
Есть рекурсивная функция ,генерирующая перестановки.Требуется,чтобы на i месте(p) не стоял i.Причем...

Перестановка без повторений
Сгенерировать перестановку N чисел без повторений. Требуется использовать циклы. Функции пока не...

Перестановка без повторений
Всем привет! У меня возникла небольшая проблема при написании программы, буду благодарна за любую...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.