【问题标题】:How to reduce execution time in this program如何减少该程序的执行时间
【发布时间】:2021-07-09 04:13:58
【问题描述】:

如果您能告诉我一些减少执行时间的方法,我将非常感谢你们。

限时: 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;
}

【问题讨论】:

  • 对于像这样的竞赛作业,两个最常见的“技巧”是找出一个等式,它可以在不使用循环或递归的情况下计算值;第二个是使用称为动态编程的东西(通常通过缓存计算值来实现,因此不必再次计算它们)。
  • N选R可以计算如this answer
  • 删除 stdio.h 函数调用,这是您执行时间的大约 99%。
  • 2 2 的输出怎么会是1
  • @AKSingh 因为只有一种方法可以从 2 个项目的集合中选择 2 个项目。其他示例表明,有五种方法可以从 5 个项目的集合中选择 1 个项目,并且有很多方法可以从 29 个项目的集合中选择 13 个项目。

标签: c algorithm execution-time


【解决方案1】:

函数调用会增加一些开销。冗余函数调用会增加很多开销。因为所有基本情况的函数调用都返回 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,0,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 循环的边界肯定可以减少。

【讨论】:

    猜你喜欢
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-03
    • 1970-01-01
    • 2012-12-31
    相关资源
    最近更新 更多