|
|
1
2
如果你使用宽度优先的蛮力,它仍然是蛮力,但至少你有保证想出最短的移动顺序,如果有答案的话。下面是一个使用宽度优先搜索的快速python解决方案。
|
|
|
2
4
我认为这应该有效:
|
|
|
3
3
这是一个很有趣的问题,所以我们试着解决它。我将从对问题的精确分析开始,看看能发现什么。在接下来的几天里,我会一个一个地把这个答案加起来。欢迎任何帮助。
尺寸问题
有
完全不同的序列
大小的问题实例
接下来,我将寻找一种方法来为每个问题实例分配一个分数,以及在所有可能的移动下该分数是如何变化的,希望找出所需移动的最小数量是多少。 大小为1的实例已排序
(我想我会用连字符代替
因此我假设
我在考虑逆问题——从有序序列开始,可以得到什么无序序列。顺序序列是由两个连字符的位置决定的,所以下一个问题是是否可以从其他顺序到达每个顺序序列。因为一个移动序列可以向前和向后执行,所以足以表明一个特定的有序序列可以从所有其他序列中到达。我选择
对于剩下的两个问题的大小2-
|
|
|
4
1
首先让我想到的是自顶向下的动态编程方法。这有点容易理解,但会消耗很多记忆。当我尝试应用自下而上的方法时,您可以尝试以下方法: 想法很简单-缓存所有的搜索结果以进行暴力搜索。它会变成这样:
这种方法的复杂性是…o(2^n),令人毛骨悚然。然而,我看不出任何合乎逻辑的方法,它可以更小,因为任何移动都是允许的。 如果找到一种应用自下而上算法的方法,它可能会更快(不需要缓存),但它仍然具有O(2^n)复杂性。
补充:
好的,我用Java实现了这个东西。代码很长,因为它总是在Java中,所以不要害怕它的大小。主算法非常简单,可以在底部找到。我认为没有比这更快的方法了(如果可以更快的话,这更像是一个数学问题)。它消耗了几吨的内存,但仍然计算得很快。
这个
|
|
|
5
0
这里有一个尝试:
因此,对于原始1100UUU0011:
对于狡猾的0101U01
然而,这并不能解决01uuu0之类的问题……但是可以通过一个标志来解决这个问题——如果你已经完成了整个算法,没有进行任何交换,并且没有解决……做点什么。 |
|
|
6
0
关于这个问题…它从不要求最优的解决方案,而这些类型的问题不希望这样。您需要编写一个通用的算法来处理这个问题,而对于长度可能为兆字节的字符串,使用蛮力搜索来找到最佳解决方案是不可行的。我也很晚才注意到,0和1的数目肯定是一样的,但我认为在一般情况下,0和1的数目可能不同,这更有趣。实际上,如果输入字符串的长度小于7,就不能保证在每种情况下都有解决方案,即使在20和1的情况下Nd 2 1s。 3号:只有一个数字,所以按定义排序(UUU0 UU1 0UU 1UU) 4号:没有办法改变顺序。如果UU位于中间,则没有移动,只有当UU位于末尾时才与两位数字交换(1UU0不移动,UU10->10UU->UUU10等) Size 5: UU in the middle can only move to the far end and not change the order of the 0s and 1s (1UU10->110UU). 一端的UU可以移动到中间,而不是更改订单,但只能移回同一端,这样它就没有任何用处(UU110->11UU0->UUU110)。唯一改变数字的方法是如果UU在一端,并与另一端交换。(UUABC->BCAUU或ABCUU->UUCAB)。这意味着,如果UU位于0或2,它可以解决0是否在中间(UU101->011UU或UU100->001UU),如果UU位于1或3,它可以解决1是否在中间(010UU->UUU001或110UU->UUU011)。其他问题已经解决或无法解决。如果我们需要处理这个案例,我会说硬编码。如果排序,则返回结果(无移动)。如果UU在中间的某个地方,把它移到末尾。从一端交换到另一端,这是唯一可能的交换,无论现在是否排序。 尺寸6:现在我们得到了这样一个位置,我们可以根据规则指定一个字符串,在那里我们可以移动,但没有解决方案。这是任何算法的问题点,因为我认为任何解决方案的一个条件都应该是它会让您知道它是否无法解决。例如,0010、0100、1000、1011、1100、1101和1110可以解决,无论UU在哪里,最坏的情况需要4个步骤来解决。只有当UU处于奇数位置时,才能求解0101和1010。0110和1001只能在UU处于偶数位置(两端或中间)时求解。 我认为最好的方法是像下面这样,但我还没有写出来。首先,确保将“1”放在列表的末尾。如果结尾当前为0,请将UU移动到结尾,然后将其移动到最后一个“1”位置-1。在这之后,您继续将UU移动到第一个“1”,然后移动到新UU之后的第一个“0”。这会将所有0移动到列表的开头。另一方面,我也看到过类似的答案,但没有考虑到最后一个角色。这可能会遇到小值的问题(即,001UUU01,不能移动到第一个1,移动到结尾00101UU,允许我们移动到开头,但在结尾00UUU110处保留0)。 我猜你可以硬编码这样的特殊情况。不过,我想可能有更好的算法。例如,您可以使用前两个字符作为“临时交换变量”。您将把UU放在那里,然后对其他人进行组合操作,以便在开始时离开UY。例如,uuuabcde可以用cd交换ab,或者用de交换de或bc(bcauude->bcadeuu->uuadebc)。 另一种可能的方法是将字符视为两个由两个基3位组成的块。 0101U0101将显示为11C11或3593。也可能是硬编码交换的组合。例如,如果您看到11UU,请将UU向左移动2。如果你看到UU00,把UU右移两个。如果看到UU100或UU101,请向右移动UU 2以获得001UU或011UU。 也许另一种可能是一些算法将0向左移动到中心,1向右移动到中心(如果给定0和1的数目相同的话)。 也许在一个只包含0和1的结构上工作会更好,这个结构有一个UU的位置。 也许更好地观察结果条件,允许UU在字符串中的任何位置,必须满足这些条件: 长度后没有0/2 前1号(长度/2-1) 也许还有更一般的规则,比如在这种情况下用10交换UU真的很好,因为“0”在UU之后,这会让您将新的00移回10的位置(10111UU->UUU111100->001111UU)。 总之,这是C中的蛮力代码。输入是一个字符串和一个空字典。它用每个可能的结果字符串作为键填充字典,并以最短步骤列表作为值: 呼叫:
它包括dotests(),它为具有给定位数(不包括uu)的每个可能字符串调用dosort:
|
|
|
7
-2
如果a是0的个数,a也是1的个数,u是我们的个数:
|
|
|
8
-2
只有两个我们? 为什么不计算0的个数并存储美国的位置呢?
会导致运行时为O(n) 甚至更好:
|
|
|
feasega · 聚合物模拟-2个节点之间的最短路线,适用于所有节点 1 年前 |
|
|
Alisa Petrova · 在有向图中更改一对顶点以创建循环 1 年前 |
|
|
b39b332d · 使用C++标准库实现高效间隔存储 2 年前 |
|
ABGR · 二叉树的直径——当最长路径不通过根时的失败案例 2 年前 |
|
|
EpicAshman · 数独棋盘程序中同一列和同一行出现两次的数字 2 年前 |