我对一个有效的算法感兴趣,可以完成以下工作:
例如:{{1,2,3},{3,4,5},{6,7,8},{5,7,9}}
我实施了一项能够完成工作的东西,但我想这可以更有效率地完成。怎么样?甚至可能有一个map
左右的恒定时间算法?
list
来实现集合,因为我删除了pick或
排除子集(快速删除)。vector
s。set
。#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <iterator>
#include <algorithm>
#include <random>
using namespace std;
random_device rd;
mt19937 rng(rd());
// pickes a random entry from a vector and returns an iterator to that element.
list<vector<int>>::iterator randomEntry(list< vector<int> >& v)
{
uniform_int_distribution<int> dis(0, v.size()-1); // guaranteed unbiased
auto it{ begin(v) };
advance(it, dis(rng));
return it;
}
int main()
{
// a collection of possible sets
list< vector<int> > collection;
collection.emplace_back( vector<int>{51,9,22} );
collection.emplace_back( vector<int>{11,5,74} );
collection.emplace_back( vector<int>{61,9,35} ); // 2nd element in common with 1st entry
collection.emplace_back( vector<int>{19,54,66} );
collection.emplace_back( vector<int>{53,86,35} ); // 3rd element in common with 3rd entry
collection.emplace_back( vector<int>{11,3,55} ); // 1st element in common with 2nd entry
// pick three -independent- sets form the collection
vector< vector<int> > picked;
set<int> elements;
while(picked.size()<3)
{
auto entry{ randomEntry(collection) }; // iterator to a randomly choosen entry
bool unused{ true };
for(const auto i : *entry)
{
if( elements.find(i) != cend(elements)) // if it already exists in elements, its already used.
unused= false;
}
if(unused)
picked.emplace_back( *entry );
collection.erase(entry); // in any chase, remove == don't pick it again.
}
// all the elements printed should only appear once.
for(const auto& i : collection)
{
for(const auto j : i)
cout<<j<<" ";
cout<<endl;
}
return 0;
}
答案 0 :(得分:1)
我有一组由三个数字组成的集合。
......目标是选择,例如3个子集,这样元素只发生一次。
......但我想这可以更有效率地完成。怎么样?
由于您的目标是选择不相交的子集的任意数 p (以3为例),这正是Set Packing problem,Karp's 21 NP-complete problems之一}。
在这个问题中,你提到每个集合都有3个元素(这次不是一个例子)。不幸的是,这个版本仍然是NPC。但幸运的是,这意味着there is an approximation algorithm with with a factor of ~50%。
因此,您不太可能找到一个多项式时间算法来解决一般 p 。看看你的代码,我怀疑它是否正确。它是一种(随机)贪婪算法,似乎有可能构建场景(输入+随机选择),悲观地认为没有解决方案。
答案 1 :(得分:0)
创建一个地图(用c ++编写哈希)
迭代集合。
对于每个集合,检查其中一个号码是否在地图中。 如果没有将数字添加到地图并将此集添加到唯一集 如果它在地图中,继续下一组。