如何减少此程序的执行时间

问题描述

如果您能告诉我一些减少执行时间的方法,我将不胜感激。

限制时间: 0.5秒

算法问题: 我想将西部的站点连接到东部的站点。 (此时,只有一座桥可以连接到一个站点。)因为我尝试建造尽可能多的桥梁,所以我尝试建造尽可能多的(N)桥以西侧的站点数量。桥梁不能相互重叠。 此时,编写一个程序来计算您可以建立多少个案例。

输入: 输入的第一行给出了测试用例的数量,'T'。 从下一行开始,每个测试用例都被赋予一个整数 (0

输出 对于每个测试用例,打印在给定条件下可以构建桥梁的用例数。

示例:

Input           Output
3                   
2 2             1
1 5             5
13 29           67863915

这是我的代码

#include <stdio.h>

int combination(int n,int r) {
    if (n == r || r == 0) return 1;
    else return combination(n - 1,r - 1) + combination(n - 1,r);
}

int main(void)
{
    int Tcase;
    int N,M;

    scanf("%d",&Tcase);

    for (int i = 0; i < Tcase; i++) {

        int total;
        scanf("%d %d",&N,&M);

        if (M - N == 0) 
            total = 1;
        else 
            total = combination(M,N);

        printf("%d\n",total);
    }

    return 0;
}

解决方法

函数调用会增加一些开销。冗余函数调用会增加很多开销。因为所有基本情况函数调用都返回 1,所以您可以计算将导致基本情况的函数调用次数。

您可以将整个递归调用堆栈展平为一个整数数组,您可以在其中计算某个状态发生的次数。此处 mem[i] 表示在您的程序版本中将调用 combination(n,i) 的次数。 (请注意,此语句仅在 while 循环的每次迭代结束时才严格正确)

int combination(int n,int r) {
    int* mem = malloc(sizeof(int)*(r+1));
    // the largest index in mem is r
    if (mem == NULL) return -1;
    for (int i = 0; i < r; ++i) {
        mem[i] = 0;
    }
    mem[r] = 1;
    // here we have mem = 0,...,1
    int total = 0;
    // total is the number of function
    // calls in the original program that
    // will result in the base case
    while (n > 0) {
        // if (r == 0) return 1;
        total += mem[0];
        mem[0] = 0;
        // if (n == r) return 1;
        if (n <= r) {
            total += mem[n];
            mem[n] = 0;
        }
        // else return combination(n - 1,r - 1) + combination(n - 1,r);
        for (int i = 0; i < r; ++i) {
            mem[i] += mem[i+1];
        }
        --n;
    }
    free(mem);
    return total;
}

即使这样也不是最理想的;可能不需要对 mem[0] 的内存访问,并且绝对可以减少第二个 for 循环的界限。