一个动态规划问题

发布于 2024-10-20 01:50:54 字数 779 浏览 2 评论 0原文

谁能帮我找到这个问题的最佳动态规划算法

在去吃晚饭的路上, 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代表Helpfile,G代表Gnold) 输出 在一行上输出

单个数字,即为晚餐而形成的最小小组数。如果不是所有程序员都能吃饭,则输出-1。

Can anyone help me find an optimal Dynamic programming algorithm for this problem

On the way to dinner, the CCC competitors are lining up for their delicious curly fries. The N (1 ≤ N ≤ 100) competitors have lined up single-file to enter the cafeteria.

Doctor V, who runs the CCC, realized at the last minute that programmers simply hate standing in line next to programmers who use a different language. Thankfully, only two languages are allowed at the CCC: Gnold and Helpfile. Furthermore, the competitors have decided that they will only enter the cafeteria if they are in a group of at least K (1 ≤ K ≤ 6) competitors.

Doctor V decided to iterate the following scheme:

* 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.

So Doctor V recorded the sequence of competitors for you. Can all the competitors dine? If so, what is the minimum number of groups of competitors to be sent to dinner?
Input

The first line contains two integers N and K.
The second line contains N characters that are the sequence of competitors in line (H represents Helpfile, G represents Gnold)
Output

Output, on one line, the single number that is the minimum number of groups that are formed for dinner. If not all programmers can dine, output -1.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

硬不硬你别怂 2024-10-27 01:50:54

我不想以实际的方式为您解决 SPOJ 问题,因此将以下内容作为多时间 DP 的存在证明。

对于 K 固定,可以用餐的字符串集合是上下文无关的。我将使用 gh 而不是 GH。例如,对于 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(N3)。

I'd prefer not to solve an SPOJ problem in a practical manner for you, so take the following as an existence proof of a poly-time DP.

For K fixed, the set of strings that can dine is context-free. I'm going to use g and h instead of G and H. For example, for K = 3, one grammar looks like

S -> ε | g S g S g S G | h S h S h S H

G -> ε | g S G

H -> ε | h S H

The idea is that either there are no diners, or the first diner dines with at least K - 1 others, between any two of which (and the last and the end) there is a string that can dine.

Now use the weighted variant of CYK to find the minimum-weight parse, where nonempty S productions have weight 1, and all others have weight 0. For K fixed, the running time of CYK is O(N3).

伪心 2024-10-27 01:50:54

子问题是让每个人在给定的排队状态下就餐所需的最小群体。有很多可能的行状态,但实际上只有少数几种,因此您的记忆可能应该使用哈希图来完成。

这是一些伪代码。

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;
    }
}

如果您已经找到该行的答案,请返回该答案。如果没有人排队,则说明您已经完成,无需再组队。

假设您无法组建任何组。然后尝试通过尝试队列中所有连续的志同道合的程序员组来证明这是错误的。如果该组足够大,可以被选中,看看移除该组后需要多少步才能让每个人都进入餐厅。跟踪所需的最少动作。

如果您找不到删除所有组的方法,请返回 -1。否则,返回删除一组后所需的最少移动量加一以说明您在此步骤中所做的移动。

The subproblem is the minimal groups needed to get everyone to dine for a given state of the line. There are a whole lot of possible line states but only a few that will actually be seen, so your memoization should probably be done with a hash map.

Here's some pseudocode.

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;
    }
}

If you already found answer for this line, return that answer. If theres no people in the line, you are already done and you don't need to form any more groups.

Assume you can't form any groups. Then try to prove this wrong by trying out all the contiguous groups of like-minded programmers in the line. If the group is big enough to get picked, see how many more moves it would take to get everyone in the resturaunt after removing this group. Keep track of the least moves needed.

If you couldn't find a way to remove all the groups, return -1. Otherwise, return the least moves needed after removing a group plus one to account for the move you made on this step.

压抑⊿情绪 2024-10-27 01:50:54

分而治之怎么样?在中间附近的某个位置取一个(可移动的)组,在其两侧各取两个组,比如说……HHHGGGGGGHHHHH…… - 现在有两种可能性。这两组 H 要么在同一组用餐,要么不同。如果他们在同一组中用餐,那么他们之间的那些 G 必须作为一组恰好这些 G 被移除(所以你不妨尝试将其作为你的第一步)。如果没有,那么您可以分别求解左右子列表。无论哪种情况,您都会得到一个更短的递归列表。

How about divide and conquer? Take a (removable) group somewhere near the middle, and the two groups either side of it, say ...HHHGGGGGHHHHH.... - now there's two possibilities. Either those 2 sets of H's dine in the same group, or they don't. If they dine in the same group, then those G's between them must be removed as a group of precisely those G's (so you may as well try that as your first move). If they don't, then you can solve for the left and right sublists separately. Either case, you've got a shorter list to recurse on.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文