安排人员排队(Uva - 10128)

时间:2017-07-08 08:07:58

标签: dynamic-programming backtracking onlinejudge

我正在尝试解决UVa Online Judge上的问题Uva-10128 (Queue)。我找不到解决这个问题的方法。我在互联网上搜索,发现大多数人通过使用DP进行预先计算来解决这个问题。

DP[1][1][1] = 1;
for(N = 2; N <= 13; N++)
    for(P = 1; P <= N; P++)
        for(R = 1; R <= N; R++)
           DP[N][P][R] = DP[N-1][P][R]*(N-2) + DP[N-1][P-1][R] + DP[N-1][P][R-1];

以上代码段取自https://github.com/morris821028/UVa/blob/master/volume101/10128%20-%20Queue.cpp

有人可以解释上面代码中使用的公式。

由于

1 个答案:

答案 0 :(得分:1)

当你计算DP[N][P][R]时,你会看到队列中最小的人的位置。因为他是最小的,他不能阻止任何人。但如果他不站在队列的任何一端,他就会受阻。

如果他是队列中的第一个人,他就会从队伍的开头看到他。因此,如果我们删除了他,则该队列包含N-1个人,您只能从一开始就看到P-1个人,但最后仍会R个人。因此,有DP[N-1][P-1][R]种组合。

如果他在中间,那么通过删除他我们仍然可以看到PR人。由于中间有N-2个位置,因此有DP[N-1][P][R] * (N-2)个组合。

如果他是队列中的最后一个人,我们会得到DP[N-1][P][R-1]个组合。推理与第一种情况完全相同。

因此DP[N][P][R]的组合总数是所有三种情况的总和。