Подсчитать уникальные подмножества размера k с некоторыми S

Команда 7 сталкивается с ужасным противником. Его можно победить только с помощью специального
комбинация силовой атаки четверной комбинации (1 <= S <= 10 ^ 9).
Наруто, Саске, Сакура и Какаши должны атаковать одновременно
выполнить комбо. Каждый из них может выбрать из N (1 <= N <= 1000) атак, каждая из которых имеет свои силы (0 <= я < N 1 <= си <= 10 ^ 9). Сильные стороны отдельных атак составляют
сила комбо.

Есть ли правильная комбинация, которую они могут использовать? Обратите внимание, что то же самое
атаки доступны для всех из них.

Вы должны написать функцию, которая принимает входные данные следующим образом:
целое число N как число атак, целочисленный вектор s[] как
сильные стороны N атаки и целое число S как требуемая сила
комбо. Установите выходную переменную в число различных допустимых
комбо.

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

Входные данные: 1 {1} 4

Выход: 1 ===>{1,1,1,1}

Входные данные: 2 {1,2} 5

Выход: 1 ===> {1,1,1,2}

Ниже мой код, он проходит только 3 тестовых случая из 10. Я не знаю тестовых случаев, так как это была некоторая онлайн-подача кода.

Мой алгоритм:
1) Создать хеш с индексами в виде суммы пар из входного массива и значения в качестве отдельных элементов, вносящих вклад в сумму
2) Итерируйте по хешу и посмотрите, есть ли i в хеше k-i
3) Подсчитайте вышеуказанные индексы и верните count / 2, поскольку мы рассчитываем как для H (i), так и для H (k-i)

Пожалуйста, просмотрите код и скажите мне, какие сценарии, по вашему мнению, код не будет производить правильно o / p.

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<map>
#include<set>

const int noOfPalyers = 4;

int validCombo(int input1,int input2[],int input3)
{
//Write code here
int count = 0;
std::vector<int> vec;
int size =input1*noOfPalyers;
for(int i = 0; i < input1; i++)
{
for(int j = 0; j < noOfPalyers;j++)
{
vec.push_back(input2[i]);
}
}

std::vector< std::set< std::pair<int, int> > > vecHash;
//vecHash.reserve(size*size);

for(int i =0; i < (size*size); i++)
{
vecHash.push_back(std::set< std::pair<int, int> >());
}

for(int i =0; i < size; i++)
{
for(int j =1; j < size; j++)

{
int key = vec[i] + vec[j];
if(vec[i]<= vec[j])
vecHash[key].insert(std::make_pair(vec[i], vec[j]));
else
vecHash[key].insert(std::make_pair(vec[j], vec[i]));

}
}

for(int i = 0; i < input3; i++)
{
if(vecHash[i].size() > 0 &&  i < input3)
{
if(vecHash[input3-i].size() > 0)
{
std::set< std::pair<int, int> >::iterator iter, iter2;
for(iter=vecHash[i].begin(); iter!=vecHash[i].end();++iter)
{

for(iter2=vecHash[input3-i].begin(); iter2!=vecHash[input3-i].end();++iter2)
{
std::cout<<(*iter).first<<","<< (*iter).second<<",";
std::cout<<(*iter2).first<<","<< (*iter2).second;
std::cout<<"\n";
count++;
}

}
}
}
}

return (count ==1 ? count: count/2);

}

int  main()
{
int i = 3;
int arr[] = {1,2,3};
int j = 7;
int arr1[] ={1};
std::cout <<"o/p == "  << validCombo(i, arr, j)<< "\n";
std::cout <<"o/p == "  << validCombo(1, arr1, 4);//getch();
return 0;
}

0

Решение

UPD. Боже мой, теперь я понял ваш комментарий 🙂 и вижу, что вы пытались решить его так же, как я написал. Во всяком случае, я надеюсь, что вы найдете некоторые части моего объяснения полезными. Прежде всего, вы не используете хеш-функции (я знаю, что функция тождества — это хеш-функция, но в нашем случае это не очень хорошая функция).
Тоже не поняла твоего count логика … думаю, вам нужно прочитать Two combinations are different if they differ in strength of at least one attack used. снова расстаться и проверить count логика.

Есть только мои первые мысли. Надеюсь, это может быть полезно.

==================================

Вы знаете, эта проблема о том, чтобы иметь конкретную сумму из 4 чисел из набора. Давайте представим, что у нас всего 2 героя (так что в нашей сумме 2 термина):

a + b = S,

где a, b — сильные стороны атаки из набора из N чисел (назовем его T). Количество разных a + b суммы N ^ 2. Простое вычисление всех этих сумм и затем поиск тех, которые равны S, не дает нам хорошего решения. Эта проблема может быть решена с большей сложностью.

Если бы мы могли найти быструю функцию, такую ​​что:

F(a) = F(S - b)

мы бы пересчитали все F (S — b), затем зациклили бы все aи нашел, какие из них удовлетворяют равенству выше. Вы упомянули хеш Хэш-функции могут сделать это. Нам нужен такой хеш-функция для отображения всех чисел из множества T в диапазоне [0, N]. Потому что у нас просто не больше N разных a«S.
Но у нас есть небольшая проблема здесь:

  • F(a) = F(S - b) просто значит a может быть равен S - b, К счастью, это не большая проблема,
  • потому что основная сила это: F(a) != F(S - b) средства a != S - b,

Хорошо, как вы видите, у нас есть алгоритм для решения a + b = S проблема с амортизированной O (N) сложностью. Звучит хорошо и многообещающе, верно? 🙂

==================================

Теперь вернемся к вашей проблеме:

a + b + c + d = S

Моя идея пересчитать все f(a + b) с O (N ^ 2) и сохраните их так (предупреждение! просто псевдокод):

vector<int> hash = new vector<int>(with size N)
foreach (a in T)
foreach (b in T)
{
int x = OurHashFunc(a + b);  // a + b <= 2 * 10^9 so it never overflows int
if (hash[x] == null)
hash[x] = new vector<pair<int,int>>
hash[x].push_back(new pair<int, int>(a, b));
}

Мы сохраняем пары (a, b), чтобы иметь возможность восстановить начальную сумму. Затем, если наш OurHashFunc является аддитивным, преобразуйте нашу начальную проблему следующим образом:

a + b + c + d = S             // apply hash func =>
f(a + b) + f(c + d) = f(S)    // rename =>
x + y = Z                     // wow, I bet I've already seen this equation ;)

Теперь задача о сумме в 4 члена сводится к задаче о сумме из 2 членов с издержками O (N ^ 2).
Я думаю, что это сокращение может быть продолжено: задача 2 ^ k-членов должна иметь решение avg O (N ^ k).

0

Другие решения


По вопросам рекламы [email protected]