有若干个选手,每个选手有打某一个或几个位置的能力,每只队伍有N个不同位置。怎样组合这些选手可以组合出最多的队伍,队伍最多是几支?
以下是我假设N=8时,使用贪心算法求最优解的过程。此算法思路较为简单,基本可以求出最优解,但还有不少可以优化的地方。望大家不吝赐教其他算法或优化算法。
public class Match
{
protected Map<Integer, Integer> map = new TreeMap<Integer, Integer>();
protected MatchComparator comp = new MatchComparator();
/**
* @param args
*/
public void main(List<Integer> nengli,List<Integer[]> talents)
{
// List<Integer> nengli = new ArrayList<Integer>();
// nengli.add(1);
// nengli.add(2);
// nengli.add(4);
// nengli.add(8);
//
// int[] a1 =
// { 1, 2, 4, 8 };
// int[] a2 =
// { 1, 2 };
// int[] a3 =
// { 2 };
// int[] a4 =
// { 4, 8 };
// int[] a5 =
// { 1, 2 };
// int[] a6 =
// { 2 };
// int[] a7 =
// { 4, 8 };
// int[] a8 =
// { 4, 8 };
// List<int[]> talents = new ArrayList<int[]>();
// talents.add(a1);
// talents.add(a2);
// talents.add(a3);
// talents.add(a4);
// talents.add(a5);
// talents.add(a6);
// talents.add(a7);
// talents.add(a8);
//构建人才分类
Map<Integer, Integer> pmap = new HashMap<Integer, Integer>();
for (Integer[] arr : talents)
{
int sum = 0;
for (int i : arr)
{
sum += i;
}
if (pmap.get(sum) == null)
{
pmap.put(sum, 0);
}
pmap.put(sum, pmap.get(sum) + 1);
}
//构建稀缺能力Map
// Map<Integer, Integer> map = new TreeMap<Integer, Integer>();
for (Integer i : nengli)
{
map.put(i, 0);
}
for (Integer[] arr : talents)
{
for (int i : arr)
{
map.put(i, map.get(i) + 1);
}
}
//获取最稀缺资源排名
Collections.sort(nengli, comp);
//已填充缓存
Set<Integer> set = new HashSet<Integer>();
// List<Integer[]> resultLst = new ArrayList<Integer[]>();
// Integer[] tempresult = new Integer[nengli.size()];
//循环填充
int count = 0;
find:for (Integer[] is : talents)
{
//从最稀缺资源开始填充
for (Integer nl : nengli)
{
//已填充跳过
if(set.contains(nl))
{
continue;
}
//查找有最稀缺能力的最不稀缺能力的人才
// System.out.println("寻找有"+nl+"能力的人才");
if (pmap.get(nl) != null && pmap.get(nl) > 0)
{
//人才分类去掉1个人才
pmap.put(nl, pmap.get(nl)-1);
//能力计数减掉该人才的能力
map.put(nl, map.get(nl)-1);
set.add(nl);
// tempresult[set.size()-1] = nl;
//填充下一个
break;
}
// System.out.println(nl);
int result = getRareNl2(nl,nl, nengli,-1, pmap);
if (result != 0)
{
//人才分类去掉1个人才
pmap.put(result, pmap.get(result)-1);
//能力计数减掉该人才的能力
Integer[] nls = divideNengli(result);
for (int n : nls)
{
map.put(n, map.get(n)-1);
}
set.add(nl);
// tempresult[set.size()-1] = result;
//填充下一个
break;
}
else
{
//填充失败,结束
break find;
}
}
//重新排序
Collections.sort(nengli, comp);
// 填充一轮,计数加1
if(set.size()==nengli.size())
{
set.clear();
count++;
// resultLst.add(tempresult);
// tempresult = new Integer[nengli.size()];
}
}
System.out.println("最终结果:"+count);
// for (Integer[] tem : resultLst)
// {
// System.out.println("最终结果排列:"+Arrays.toString(tem));
// }
// System.out.println("最终剩余项:"+Arrays.toString(tempresult));
}
/**
* 分解出所有能力
* @param result
* @return
*/
private static Integer[] divideNengli(int result)
{
List<Integer> lst = new ArrayList<Integer>();
int pow = 0;
while(result!=0)
{
int surplus = result%2;
if(surplus==1)
{
int nl = (int)Math.pow(2, pow);
lst.add(nl);
}
result = result/2;
pow++;
}
return lst.toArray(new Integer[lst.size()]);
}
private static int getRareNl2(Integer source,Integer nengli, List<Integer> nengli2,int x, Map<Integer, Integer> pmap)
{
//获取有最稀缺能力的人才
for (int i = nengli2.size() - 1; i > x; i--)
{
int left = nengli2.get(i);
if(source==left)
{
continue;
}
if (pmap.get(nengli + left) != null && pmap.get(nengli + left) > 0)
{
return nengli + left;
}
// System.out.println(nengli + left);
int result = getRareNl2(source,nengli + left, nengli2,i, pmap);
if (result != 0)
{
return result;
}
}
return 0;
}
public class MatchComparator implements Comparator<Integer>
{
// Map<Integer, Integer> map = null;
//
// public MatchComparator(final Map<Integer, Integer> map)
// {
// this.map = map;
// }
@Override
public int compare(Integer o1, Integer o2)
{
return map.get(o1) - map.get(o2);
}
}
}