正则 最近配对匹配_朋友配对问题

正则 最近配对匹配

This is a standard interview problem to find the number of ways of pairing between N friends using dynamic programming.

这是一个标准的面试问题,目的是找到使用动态编程在N个朋友之间进行配对的方式

Problem statement:

问题陈述:

There are N friends, each one of them can remain single or can be paired up with some other friend. Each friend can be paired only once. Find out the total number of ways to do so. Since inputs are big return answer MOD 10^9+7.

N个朋友,每个朋友可以保持单身,也可以与其他朋友配对。 每个朋友只能配对一次。 找出这样做的总数。 由于输入很大,因此请回答MOD 10 ^ 9 + 7

    Input:
    Test case t
    t no of lines with value of N
    e.g.
    3
    5
    4

    1<=t<=100
    1<=N<=100

    Output:
    t number of lines

Example:

例:

    Input:   t=3, n=3
    Output:  4

    Input:   n=4
    Output:  10

    Input:   n=5
    Output:  26

Explanation with example:

举例说明:

Let there are N number of friends, say x1, x2, ..., xn

设N个朋友,例如x 1 ,x 2 ,...,x n

Now, possible orderings can be:

现在,可能的订购可以是:

  1. All are single. {x1, x2, ... , xn}

    全部都是单身。 {x 1 ,x 2 ,...,x n }

  2. x1 is single , others are paired contiguously(if n is odd). {x1, (x2, x3), ...}

    x 1是single,其他则连续配对(如果n为奇数)。 {x 1 ,(x 2 ,x 3 ),...}

    So on. So if we try to figure out a formula then to observe that.

    等等。 因此,如果我们尝试找出一个公式,则可以进行观察。

    For any x

    对于任何x

    i

    一世

    1. i can be kept single可以单身
    2. i can be paired with any other xi可以与任何其他x j provided i≠jj配对,只要i≠j

Let f(n)= number of ways to pair for input N

f (n) =输入N配对的方式数

Considering the above two facts about xi

考虑关于x i的上述两个事实

If xn is kept single then f(n) = f(n-1) (same as number of ways excluding xn)
If xn is paired with any other friend then f(n)=(n-1)*f(n-2) (number of ways xn can be paired * sub-problem excluding xn and the paired one with it)

如果x n保持单个,则f (n)= f (n-1) (与不包括x n的方式相同)
如果x n与任何其他朋友配对,则f (n)=(n-1)* f (n-2) (xn可以配对的方式数量*子问题,不包括x n以及与之配对的子问题)

So the recursion function to solve the problem:

所以递归函数解决了这个问题:

    f(n)=f(n-1)+(n-1)*f(n-2)

    For n=4
    Friends are {1, 2, 3, 4}

    So the pairings can be are:
    {1, 2, 3, 4}
    {1, 2, (3, 4)}
    {1, (2, 3), 4}
    {(1, 4), 2, 3}
    {(1, 3), 2, 4}
    {(2, 4), 1, 3}
    {(1, 2), 3, 4}
    {(1, 2), (3, 4)}
    {(1, 3), (2, 4)}
    {(1, 4), (2, 3)}
    
    So total 10 possible type of pairings, hence output is 10

    So the recursion tree for the above would be:
    

Recursion tree

We see that we are evaluating many sub-problem several times. Like f(2) has been evaluated more than one time and the same also for others. It’s easily understandable that for such small input there are so many repeated computations, then for higher inputs, how many overlapping there will be. Here comes the need for DP, where we can use tabulation to solve bigger subproblems using smaller ones.

我们看到我们正在多次评估许多子问题。 像f(2)一样,已经被评估了不止一次,其他情况也一样。 不难理解,对于这么小的输入,会有如此多的重复计算,然后对于更高的输入,将有多少重叠。 这就是对DP的需求,在这里我们可以使用列表来使用较小的子问题解决较大的子问题。

Problem Solution:

问题方案:

Recursive Algorithm:

递归算法:

    Function(n):
        If n==0 or n==1 
            Return 1
        Else
            Return Function(n-1)+(n-1)*Function(n-2); 

Conversion to DP:

转换为DP:

    For tabulation we need arr[n+1] to store
        arr[0]=1
        arr[1]=1
    To fill the higher values,
        for i=2 to n
            arr[i]=arr[i-1]+(i-1)*arr[i+1]
        End for

To avoid Time Limit Exceed:

为避免超过时间限制:

Since there are multiple test cases, we may get TLE even after using DP. To avoid that best way is to pre-compute the table up to input constraint. According to our example,

由于存在多个测试用例,因此即使使用DP后我们也可能获得TLE 。 为了避免这种最好的方法,是预先计算表以达到输入约束。 根据我们的示例,

    1<=N<=100

So better pre-compute arr[101] and return O(1) in time executing the test case query. No need to construct the table again and again for each test case.

因此,更好的预计算arr [101]并在执行测试用例查询时及时返回O(1) 。 无需为每个测试用例一次又一次构造表。

C++ implementation:

C ++实现:

#include <bits/stdc++.h>
using namespace std;

#define N 100
#define MOD 1000000007
long long int arr[N + 1] = { 0 }; //DP Table

int main()
{
    arr[0] = 1; //f(0)=1
    arr[1] = 1; //f(1)=1

    //pre-compute the table
    for (int i = 2; i <= N; i++) {
        arr[i] = (arr[i - 1] % MOD + ((i - 1) * arr[i - 2]) % MOD) % MOD;
    }

    int t, n;

    cout << "Enter number of test cases: ";
    cin >> t;

    for (int i = 0; i < t; i++) {
        cout << "Enter number of friends: ";
        cin >> n;
        //just executing query from pre-computed values
        cout << "Answer: " << arr[n] << endl;
    }

    return 0;
}

Output

输出量

Enter number of test cases: 3
Enter number of friends: 4
Answer: 10
Enter number of friends: 5
Answer: 26
Enter number of friends: 3
Answer: 4


翻译自: https://www.includehelp.com/icp/friends-pairing-problem.aspx

正则 最近配对匹配

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值