这是2015年ICPC西北规划竞赛的问题之一,我想知道是否有更简单或更有效的方法。
问题在于:
“弗雷德喜欢穿不匹配的袜子。这有时意味着他必须提前计划。 假设他的袜子抽屉有一个红色,一个蓝色和两个绿色袜子。如果他穿了 蓝色的红色,他穿着匹配的绿色袜子。他把两个放在一起 如果他将红色与绿色配对,然后将蓝色与绿色配对则不匹配。鉴于 他的袜子抽屉的内容,他可以将多少双不匹配的袜子放在一起?“以下是一个示例输入:
2017/11/01 04:27:22 [error] 13451#13451: *1 open() "/usr/share/nginx/html/static/img/search.svg" failed (2: No such file or directory), client: 127.0.0.1, server: asknow.local, request: "GET /static/img/search.svg HTTP/1.1", host: "www.asknow.local"
Color 1 -> 4 socks
Color 2 -> 3 socks
Color 3 -> 7 socks
Color 4 -> 11 socks
我正在做的方法是首先将输入读入数组并逐渐对其进行排序。这样我就会在阵列末尾拥有最多的袜子。从这里开始,我基本上比较Color 5 -> 4 socks
和arr[i]
并获得它们之间的最小值。将其添加到总数中,保存剩余部分,然后重复进入数组的过程。例如,使用示例输入它看起来像这样:
排序数组:arr[i-1]
[3,4,4,7,11]
1:3 socks
---> 1:3 socks
---> 1:0 socks
---> 1:0 socks
2:4 socks
---> 2:4 socks
---> 2:1 socks
---> 2:1 socks
3:4 socks
---> 3:4 socks
---> 3:0 socks
---> 3:0 socks
4:7 socks
---> 4:0 socks
---> 4:0 socks
---> 4:0 socks
5:11 socks
---> 5:4 socks
---> 5:0 socks
---> 5:0 socks
总计= 14种不匹配的袜子组合。这似乎太天真了一种方法。有没有人对如何优化它有任何想法?如有必要,我可以发布我的代码。
答案 0 :(得分:1)
我认为通过检查不同袜子颜色的所有可能分组到2桩,可以找到最佳解决方案。对于每个这样的分组p
可以制作奇数对袜子,其中p
是最小桩中的袜子数。您希望分组提供最大p
。您可以递归地将所有可能的袜子分组生成为2个桩。
这里有一些Java代码来说明:
public static void main(String[] args)
{
int[] socks = {3,4,4,7,11};
System.out.println(count(0, 0, socks, 0));
}
static int count(int a, int b, int[] socks, int i)
{
if(i == socks.length)
{
return Math.min(a, b);
}
return Math.max(count(a+socks[i], b, socks, i+1),
count(a, b+socks[i], socks, i+1));
}
输出:
14
答案 1 :(得分:1)
“希望在这个时候更正确!”方法强>
步骤1:检查是否剩下2种或更多颜色。如果没有或者剩下一种颜色你就完成了(找不到更多对)。
步骤2:找到一个具有最低非零数的颜色
步骤3:排除最低计数的颜色(如果所有颜色具有相同的计数);找到最高计数并确定共享最高计数的颜色数
步骤4:排除最低计数的颜色和最高计数的所有颜色;试图找到第二高的数量。
步骤5a:如果计数第二高,则计算amount_to_pair = min(highest_count - second_highest_count, lowest_count)
。
步骤5b:如果没有第二高的计数,请计算amount_to_pair = lowest_count
。
步骤6:通过将袜子与具有最低计数的袜子配对,尽可能均匀地使用具有最高计数的颜色(例如,如果有9个红色袜子,20个蓝色袜子和20个绿色,则创建amount_to_pair
对袜子;然后创造5对“红色和蓝色”对和4“红色和绿色”对。
第7步:转到第1步。
示例(评论中提到的病理案例):
初始条件
Color 1 -> 1 socks
Color 2 -> 20 socks
Color 3 -> 80 socks
Color 4 -> 81 socks
第一次迭代:
Color 1 -> 1 socks (lowest non-zero count)
Color 2 -> 20 socks
Color 3 -> 80 socks (2nd highest count)
Color 4 -> 81 socks (highest count)
Amount to remove = min(81-80, 1) = 1
Color 1 -> 1-1=0 socks (lowest non-zero count)
Color 2 -> 20 socks
Color 3 -> 80 socks
Color 4 -> 81-1=80 socks (highest count)
Results so far:
(1 pair of colour 1 and colour 4)
第二次迭代:
Color 1 -> 0 socks
Color 2 -> 20 socks (lowest non-zero count)
Color 3 -> 80 socks (highest count)
Color 4 -> 80 socks (highest count)
Amount to remove = 20
Color 1 -> 0 socks
Color 2 -> 20-20=0 socks (lowest non-zero count)
Color 3 -> 80-(20/2)=70 socks (highest count)
Color 4 -> 80-(20-20/2)=70 socks (highest count)
Results so far:
(1 of colour 1 and colour 4)
(10 of colour 2 and colour 3)
(10 of colour 2 and colour 4)
第三次迭代:
Color 1 -> 0 socks
Color 2 -> 0 socks
Color 3 -> 70 socks (lowest non-zero count)
Color 4 -> 70 socks (highest count)
Amount to remove = 70
Color 1 -> 0 socks
Color 2 -> 0 socks
Color 3 -> 70-70=0 socks (lowest non-zero count)
Color 4 -> 70-70=0 socks (highest count)
Results so far:
(1 of colour 1 and colour 4)
(10 of colour 2 and colour 3)
(10 of colour 2 and colour 4)
(70 of colour 3 and colour 4)
原始方法
警告:以下方法在各种病理情况下会给出错误的结果(并且已由上述算法更新/替换)。我把它留在这里给出一些评论的背景
开始条件:
Color 1 -> 4 socks
Color 2 -> 3 socks
Color 3 -> 7 socks
Color 4 -> 11 socks
Color 5 -> 4 socks
查找最高计数和最低计数;并取消最低计数,以便它不再存在:
Color 1 -> 4 socks
Color 3 -> 7 socks
Color 4 -> 11-3=8 socks
Color 5 -> 4 socks
Results so far:
(3 of colour 2 and colour 4)
再做一次:
Color 3 -> 7 socks
Color 4 -> 8-4=4 socks
Color 5 -> 4 socks
Results so far:
(3 of colour 2 and colour 4)
(4 of colour 1 and colour 4)
再做一次:
Color 3 -> 7-4=3 socks
Color 5 -> 4 socks
Results so far:
(3 of colour 2 and colour 4)
(4 of colour 1 and colour 4)
(4 of colour 4 and colour 3)
再做一次:
Color 5 -> 4-3=1 sock
Results so far:
(3 of colour 2 and colour 4)
(4 of colour 1 and colour 4)
(4 of colour 4 and colour 3)
(4 of colour 3 and colour 5)
停止,因为只剩下一种颜色。
答案 2 :(得分:1)
构建图形数据结构。每个袜子都是顶点。从每个顶点到另一种颜色的所有顶点创建边。
现在找到maximum matching的力量 - 没有公共顶点的边集的大小。
您可以在多项式时间O(V ^ 2 * E)中使用Edmonds algorithm构建最大匹配。似乎该任务的图形将是密集的,因此复杂性倾向于O(V ^ 4)。还存在Micali和Vazirani算法,其复杂性较低(不了解实现硬度)。
如果你的任务本身不需要最大匹配 - 只有边数,那么可以使用基于Tutte矩阵定理的随机Lovasz算法计算该值。 (我没有找到简明的英文描述 - 或许术语可能有所不同,俄语中的短文是here)