任何人都可以帮我找到this problem
的最佳动态编程算法在去吃饭的路上,CCC的竞争对手正在为他们美味的卷曲薯条排队。 N(1≤N≤100)的竞争对手已经排成一档进入自助餐厅。
经营CCC的V博士在最后一刻意识到,程序员只是讨厌排在使用不同语言的程序员旁边。值得庆幸的是,CCC只允许使用两种语言:Gnold和Helpfile。此外,竞争对手已决定,如果他们属于至少K(1≤K≤6)的竞争对手,他们将只进入自助餐厅。
V博士决定迭代以下方案:
* He will find a group of K or more competitors who use the same language standing next to each other in line and send them to dinner.
* The remaining competitors will close the gap, potentially putting similar-language competitors together.
因此,V博士为您录制了竞争对手的序列。所有竞争对手都可以用餐吗?如果是这样,竞争对手的最低数量是多少? 输入
第一行包含两个整数N和K. 第二行包含N个字符,它们是行中的竞争者序列(H代表帮助文件,G代表Gnold) 输出
在一行上输出单个数字,该数字是为晚餐形成的最小组数。如果不是所有程序员都可以用餐,则输出-1。
答案 0 :(得分:8)
我不希望以实际方式为您解决SPOJ问题,因此请将以下内容作为多时间DP的存在证明。
对于K固定,可以用餐的字符串集是无上下文的。我将使用g
和h
代替G
和H
。例如,对于K = 3,一个语法看起来像
S -> ε | g S g S g S G | h S h S h S H
G -> ε | g S G
H -> ε | h S H
这个想法是,要么没有用餐者,要么第一个用餐者至少用K-1吃饭,其中任何两个(以及最后和最后一个)之间都有一个可以用餐的字符串。
现在使用CYK的加权变量来查找最小权重解析,其中非空S生成权重为1,其他所有权重为0.对于K固定,CYK的运行时间为O(N 3 )。
答案 1 :(得分:0)
子问题是让每个人都能在线路的特定状态下用餐所需的最小组。有很多可能的行状态,但实际上只会看到一些,所以你的memoization可能应该用哈希映射完成。
这是一些伪代码。
int dine(string line){
if(hashmap.contains(line)){
return hashmap.get(line);
}
if(line.length == 0){
return 0;
}
best = N+1;
for(i=0;i<line.length;i=j){
type = string[i];
j = i+1;
while(type == string[j]){
j++;
}
if(j-i >= K){
result = dine(string.substring(0,i-1) + string.substring(j,string.length));
if(result > 0 && result < best){
best = result;
}
}
}
if(best == N+1){
hashmap.insert(line, -1);
return -1;
}
else {
hashmap.insert(line, best+1);
return best+1;
}
}
如果您已找到此行的答案,请返回该答案。如果该行中没有人,那么您已经完成了,并且您不需要再组建任何组。
假设您无法组建任何组。然后尝试通过尝试排队中所有相似的志同道合的程序员组来证明这是错误的。如果该组足够大,可以被选中,那么看看在删除该组后让所有人进入resturaunt需要多少动作。跟踪所需的最少动作。
如果找不到删除所有组的方法,请返回-1。否则,在删除组加1后,返回所需的最少移动,以说明您在此步骤中所做的移动。
答案 2 :(得分:0)
分而治之怎么样?在中间附近的某个地方取一个(可移动的)小组,然后在它的两边各做一组,说...... HHHGGGGGHHHHH .... - 现在有两种可能性。要么是那两组H在同一组中用餐,要么他们没有。如果他们在同一组中用餐,那么他们之间的那些G必须作为一组精确地那些G被移除(所以你可以尝试将其作为你的第一步)。如果他们不这样做,那么您可以分别解决左右子列表。无论哪种情况,你都有一个较短的清单来递减。