Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перебор "двоичный", но без рекурсии, перебрать все комбинации элементов 
:(
    Опции темы
AGENTxXx
Дата 10.6.2012, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 8.6.2009

Репутация: нет
Всего: 1



Добрый день, Дорогие форумчане..
Может кто видит, как можно сделать более оптимально:
У нас есть рюкзак, его общий объем, вещи и их вес.
Т.е. предположим, что у нас есть 5 вещей.
Я их представляю как массив из 5 элементов, в котором 1, значит берем вещь, 0 - значит не берем.
Необходимо перебрать все варианты и найти такой, в котором мы бы взяли в рюкзак вещи, которые в сумме дают максимальный вес, т.е.
11111
01111
00111
00011
00001
10111
10011
и в таком духе...

В общем необходим как раз такой перебор реализовать. А к рюкзаку уже сам прикручу.
Я это делал с помощью рекурсии и все хорошо получается, но т.к. сейчас задание на CUDA, а она пока что не поддерживает рекурсию (у меня компиль ругается, хотя в 4 вроде как сказано, что уже поддерживает).

Из своих соображений:
Перегонять двоичное число разбивая его по символьно в массив.
Еще как вариант:
Код

    int counts=4;
    int tmp_counts;
    int take[5]={1,1,1,1,1};
    tmp_counts=counts;
    for (int l=0; l<32; l++)
    {
        counts=tmp_counts;
        while(counts>-1)
        {
            if (take[counts]==0)
            {
                take[counts]=1;
                counts=-1;
            }
            else
            {
                take[counts]=0;
                counts--;
            }
        }
        for (int k=0; k<rnk; k++)
        {
            printf("%d ",take[k]);
        }
        printf("\r\n");
    }

но думаю данный код уж точно не оптимальный(((

И если есть ребята, которые с технологией CUDA работали, может подскажите, как лучше параллелить данную задачу. Я пока что делал так:
Если 2 потока, то начинаем со второй вещи, а автоматом для первого потока кладем эту вещь в рюкзак.
если 4 потока, то так же делаем, но с 2мя вещами.
Как заметно, минус данной логики - то, что количество потоков должно быть кратно 2ке, иначе будет неправильно распределяться.


В общем буду благодарен, если поможете советом или алгоритмом))


Это сообщение отредактировал(а) AGENTxXx - 10.6.2012, 20:50
PM MAIL   Вверх
586
Дата 10.6.2012, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

Репутация: 10
Всего: 146



Код
for(int i=0; i<32; ++i)
{
    if(i & 1) { берём вещь №1 }
    if(i & 2) { берём вещь №2 }
    if(i & 4) { берём вещь №3 }
    if(i & 8) { берём вещь №4 }
    if(i & 16) { берём вещь №5 }
}


Это сообщение отредактировал(а) 586 - 10.6.2012, 20:37
PM   Вверх
AGENTxXx
Дата 10.6.2012, 20:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 8.6.2009

Репутация: нет
Всего: 1



586, можете код пояснить ваш, а то я что т не догоняю.....
PM MAIL   Вверх
disputant
Дата 10.6.2012, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 28.11.2011

Репутация: нет
Всего: 3



Четвертый том Кнута вам в помощь, или если на русском - то превыпуск 2 четвертого тома. В Интернете точно имеется smile

Мое мнение - поскольку вам веса считать - лучше кодом Грея (по сути, добавляется или убирается один предмет, так что вес легко считать - в одно действие, много суммировать не надо - так что будет работать быстрее всего.

PM MAIL   Вверх
AGENTxXx
Дата 10.6.2012, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 231
Регистрация: 8.6.2009

Репутация: нет
Всего: 1



Погуглил.. Тоже видел в одном месте с помощью "кода Грея" считали.
Хорошо, посмотрю тогда в этом направлении тоже.
Но опять же вопрос: если применять код Грея, распараллелить там можно?
Нет ли зависимости от предыдущего действия?

Мне параллелить нужно, без этого не прокатит.. Сейчас так сказать первый вариант уже со своим алг. сварганил, но он у меня пока что очевидно не выглядит параллелевидным.. так что нужно думать еще....
PM MAIL   Вверх
disputant
Дата 11.6.2012, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 28.11.2011

Репутация: нет
Всего: 3



Цитата(AGENTxXx @ 10.6.2012,  21:36)
Погуглил.. Тоже видел в одном месте с помощью "кода Грея" считали.
Хорошо, посмотрю тогда в этом направлении тоже.
Но опять же вопрос: если применять код Грея, распараллелить там можно?
Нет ли зависимости от предыдущего действия?

Мне параллелить нужно, без этого не прокатит.. Сейчас так сказать первый вариант уже со своим алг. сварганил, но он у меня пока что очевидно не выглядит параллелевидным.. так что нужно думать еще....

Честно говоря, не помню я, насколько там генерация зависит только от предыдущего состояния, но думаю, что можно.

А что, настолько большая задача, что надо параллелить? Какие реально числа предполагается считать?
тогда, может, стоит ветвление с обрезанием применить?... Все равно на реальной машине с реальным количеством ядер вряд ли порядок вытянется smile


Это сообщение отредактировал(а) disputant - 11.6.2012, 17:47
PM MAIL   Вверх
Silent
Дата 13.6.2012, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 252
Регистрация: 3.10.2006

Репутация: нет
Всего: 9



1) Получать все возможные комбинации из наборов предметов очень просто - двоичная запись чисел от 0 до 2^N-1 (т.е. для 5 - 00000, 00001, 00010, 00011, ..., 11110, 11111);
2) генерировать их также элементарно - запускаете все потоки одной пачкой;
3) вычислять, брать i-й вес или нет - определением, есть ли i-й бит.

псевдокод (с cuda не работал, но идея такая):
Код

const int n = 5;    //количество предметов
const int m = 2 << n;    //для n предметов - 2^n комбинаций
int w[n];            //массив весов
int res[];            //результаты изысканий

__global__ void kernel()
{
    int id = threadIdx.x;
    int sum = 0;
    for (int i = 0; i < n; i++, id >>= 1)
    {
        sum += w[i] * (id & 1);
    }
    res[threadIdx.x] = sum;
}

int main()
{
    kernel<<<m>>>();
    int ans = res[0], index = 0;
    for (int i = 0; i < m; i++)    //Хотя этот цикл тоже можно делать с помощью cuda (поиск максимального элемента в массиве, и его индекса)
        if (ans > res[i])
        {
            ans = res[i];
            index = i;
        }
    printf("Max weight - %d, positions: ");
    for (int i = 0; i < n; i++, index >>= 1)
        if (index & 1) printf("%d ", i);
    return 0;
}


Это сообщение отредактировал(а) Silent - 13.6.2012, 12:51
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0817 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.