Java 竞争编码-以最低成本清除所有级别:不通过所有测试用例
当我遇到这个问题时,我正在一个有竞争力的编码网站上解决问题。问题表明:Java 竞争编码-以最低成本清除所有级别:不通过所有测试用例,java,arrays,algorithm,Java,Arrays,Algorithm,当我遇到这个问题时,我正在一个有竞争力的编码网站上解决问题。问题表明: 在这个游戏中有N个等级和M种类型的可用武器。等级编号从0到N-1,武器编号从0到M-1您可以按任何顺序清除这些级别。在每个级别中,需要这些M武器的某些子集来清除此级别。如果在特定关卡,你需要购买x件新武器,你将为此支付x^2硬币。还要注意的是,你可以携带你目前拥有的所有武器到下一个级别。最初,你没有武器。你能找出所需的最低硬币数,以便你能清除所有关卡吗 输入格式 输入的第一行包含2个空格分隔的整数: N=游戏中的关卡数 M=
在这个游戏中有N个等级和M种类型的可用武器。等级编号从0到N-1,武器编号从0到M-1您可以按任何顺序清除这些级别。在每个级别中,需要这些M武器的某些子集来清除此级别。如果在特定关卡,你需要购买x件新武器,你将为此支付x^2硬币。还要注意的是,你可以携带你目前拥有的所有武器到下一个级别。最初,你没有武器。你能找出所需的最低硬币数,以便你能清除所有关卡吗 输入格式 输入的第一行包含2个空格分隔的整数: N=游戏中的关卡数 M=武器类型的数量 下面是N行。这些行的第i行包含长度为M的二进制字符串。如果 这个字符串是1,这意味着我们需要一个j型武器来清除第i级 约束
1这个问题背后的逻辑是,每次你都必须找到对应于二进制字符串的最小设置位计数,该字符串将包含迄今为止在该级别中获得的武器 例如: 我们有如下数据: 4 3 101-2位 010-1位 110-2位 101-2位 现在,由于010有最小位,我们首先计算它的成本,然后更新当前模式(使用按位OR),所以当前模式是010 接下来,我们找到当前模式的下一个最小设置位wrt 我使用了这个逻辑,首先对当前模式和给定的数字使用异或,然后对当前数字(A^B)&A使用and 因此,在操作之后,位变成这样 (101^010)和101->101-2位 (110^010)&110->100-1位 现在我们知道最小位是110,我们选择它并计算成本,更新模式等等。。 此方法返回字符串相对于当前模式的成本
private static int computeCost(String currPattern, String costString) {
int a = currPattern.isEmpty()?0:Integer.parseInt(currPattern, 2);
int b = Integer.parseInt(costString, 2);
int cost = 0;
int c = (a ^ b) & b;
cost = (int) Math.pow(countSetBits(c), 2);
return cost;
}
这个问题背后的逻辑是,每次你都必须找到一个二进制字符串对应的最小设置位计数,这个二进制字符串将包含迄今为止在该级别上获得的武器 例如: 我们有如下数据: 4 3 101-2位 010-1位 110-2位 101-2位 现在,由于010有最小位,我们首先计算它的成本,然后更新当前模式(使用按位OR),所以当前模式是010 接下来,我们找到当前模式的下一个最小设置位wrt 我使用了这个逻辑,首先对当前模式和给定的数字使用异或,然后对当前数字(A^B)&A使用and 因此,在操作之后,位变成这样 (101^010)和101->101-2位 (110^010)&110->100-1位 现在我们知道最小位是110,我们选择它并计算成本,更新模式等等。。 此方法返回字符串相对于当前模式的成本
private static int computeCost(String currPattern, String costString) {
int a = currPattern.isEmpty()?0:Integer.parseInt(currPattern, 2);
int b = Integer.parseInt(costString, 2);
int cost = 0;
int c = (a ^ b) & b;
cost = (int) Math.pow(countSetBits(c), 2);
return cost;
}
这可以通过动态规划来解决 国家将是我们目前拥有的武器的小面具 过渡将是尝试从当前状态中依次清除每个
n
可能的级别,获取我们需要的额外武器并支付费用。
在每个n
结果状态中,我们采用当前方法和所有以前观察到的方法的最小成本来实现它。
当我们已经拥有一些武器时,某些级别实际上不需要购买额外的武器;这样的转换将自动被忽略,因为在这种情况下,我们到达相同的状态,并支付相同的成本
我们从m
0的状态开始,支付0
。
最终状态是所有给定级别的按位OR,实现该状态的最低成本就是答案
在伪代码中:
let mask[1], mask[2], ..., mask[n] be the given bit masks of the n levels
p2m = 2 to the power of m
f[0] = 0
all f[1], f[2], ..., f[p2m-1] = infinity
for state = 0, 1, 2, ..., p2m-1:
current_cost = f[state]
current_ones = popcount(state) // popcount is the number of 1 bits
for level = 1, 2, ..., n:
new_state = state | mask[level] // the operation is bitwise OR
new_cost = current_cost + square (popcount(new_state) - current_ones)
f[new_state] = min (f[new_state], new_cost)
mask_total = mask[1] | mask[2] | ... | mask[n]
the answer is f[mask_total]
复杂度是
O(2^m*n)
时间和O(2^m)
内存,这对m应该是很好的,这可以通过动态规划来解决
国家将是我们目前拥有的武器的小面具
过渡将是尝试从当前状态中依次清除每个n
可能的级别,获取我们需要的额外武器并支付费用。
在每个n
结果状态中,我们采用当前方法和所有以前观察到的方法的最小成本来实现它。
当我们已经拥有一些武器时,某些级别实际上不需要购买额外的武器;这样的转换将自动被忽略,因为在这种情况下,我们到达相同的状态,并支付相同的成本
我们从m
0的状态开始,支付0
。
最终状态是所有给定级别的按位OR,实现该状态的最低成本就是答案
在伪代码中:
let mask[1], mask[2], ..., mask[n] be the given bit masks of the n levels
p2m = 2 to the power of m
f[0] = 0
all f[1], f[2], ..., f[p2m-1] = infinity
for state = 0, 1, 2, ..., p2m-1:
current_cost = f[state]
current_ones = popcount(state) // popcount is the number of 1 bits
for level = 1, 2, ..., n:
new_state = state | mask[level] // the operation is bitwise OR
new_cost = current_cost + square (popcount(new_state) - current_ones)
f[new_state] = min (f[new_state], new_cost)
mask_total = mask[1] | mask[2] | ... | mask[n]
the answer is f[mask_total]
复杂度是O(2^m*n)
时间和O(2^m)
内存,这对于m应该很好@Gassa的动态优化思想可以通过估计剩余成本的最小值和最大值来扩展,其中
minRemaining(s)=bitCount(maxState-s)
maxRemaining(s)=bitCount(maxState-s)^2
从一个优先级队列开始—并以成本+最小剩余为基础—仅为空状态,然后将此队列中尚未达到maxState的状态替换为基于n个级别的最多n个新状态:
跟踪队列中的bound=min(成本)+maxRemaining(剩余))
,
并使用位计数(maxState)^2+1初始化所有成本
extract state with lowest cost
if state!=maxState
remove state from queue
for j in 1..n
if (state|level[j]!=state)
cost(state|level[j])=min(cost(state|level[j]),
cost(state)+bitCount(state|level[j]-state)^2
if cost(state|level[j])+minRemaining(state|level[j])<=bound
add/replace state|level[j] in queue
else break
在最坏的情况下,操作的数量应该类似于动态优化,但在许多情况下会更好——我不知道最坏的情况是否会发生。可以通过估计剩余成本的最小值和最大值来扩展@Gassa的动态优化思想,其中
minRemaining(s)=bitCount(maxState-s)
maxRemaining(s)=bitCount(maxState-s)^2
从一个优先级队列开始—并以成本+最小剩余为基础—仅为空状态,然后将此队列中尚未达到maxState的状态替换为基于n个级别的最多n个新状态:
跟踪队列中的bound=min(成本)+maxRemaining(剩余))
,
并初始化al