在矩阵中以频率获得的总特殊值

时间:2015-09-20 13:37:41

标签: algorithm graph dynamic-programming

我有一个二阶矩阵(M x N),其中所有单元格都包含0,除了K特殊单元格,其中包含一个特殊值,即1.现在我需要从单元格开始说(0,0)并到达单元格(M-1,N-1)。我只能从任何细胞向右或向下移动。现在我需要找到(M-1,N-1)细胞的每个成功范围,我收集了多少特殊值以及它们的频率是多少?示例:我可以说3个路径只包含一个特殊值,我有10个路径,其中包含2个特殊值...依此类推。

我需要打印以相应频率获得的所有可能的总特殊价值对,即; (2,10) - 表示有2条路径,每条路的总特殊值为10等。

似乎找出从源到目的地的所有dfs路径,并计算从源到目的地获得的总特殊值的频率。但它的时间复杂度非常高。

如何最小化时间复杂度或如果可能的话如何使用动态编程概念?

示例:

0 0 0
0 1 1
0 0 0 
  • 这里有2条路径,总特殊值= 2,只有1条路径,总共特殊值= 0,3条路径,特殊值= 1等。

2 个答案:

答案 0 :(得分:0)

在这个问题中,通过简单地转换图形,很容易消除可能的路径。

将矩阵转换为有向图,其中每个节点都是一个特殊值。每个节点(nx , ny)仅与匹配(mx , my)

的其他节点nx <= mx && ny <= my && !(nx == mx && ny == my)相关联
    int[][] matrix = getMatrix()
    int specialNumberCount = specialNumberCount()
    int m = getM(), n = getN()

    list points

    for int x in [0 , m[
        for int y in [0 , n[
            if(matrix[x][y] == specialValue())
                points.add(point(x , y));

    int[][] adjacencSpecial = new int[specialNumberCount][specialNumberCount];
    for int i in [0 , length(points)[
        point p = points.get(i)

        for int j in [0 , length(points)[
            if j == i
                continue
            else
                point s = points.get(j)
                if p.x <= s.x AND p.y <= s.y AND (p.x != s.x AND p.y != s.y)
                    adjacencMatrix[i][j] = 1

现在,此代码会将图表的大小从M x N缩小为K。从这一点来说,运行BFS并不需要太长时间。

答案 1 :(得分:0)

不知道你是否仍然需要它,但发现了一种非常快速的方法(时间复杂度小于O(W+H)):

首先,通过向右移动移动次数(c(W+H-2,W-1))找到移动次数的二项式系数,找到可能路径的数量,然后遍历每条路径,存储这些点供以后使用。 代码:

//
//  main.c
//
//  Created by Xavier L'Heureux on 15-10-01.
//
//  This code return the number of path for each possible value in the matrix where you can only
//   go down or right.
//
//  Note that this code work also for for non-square matrices
//

#include <stdio.h>
#include <stdlib.h>

#define W 3
#define H 4

int matrix[W][H] = {
    {0,0,0,0},
    {0,0,1,1},
    {0,0,0,0}
};

int path(double p, double n){
    int x = W - 1, y = H - 1;
    int points = 0;
    while (x != 0 || y != 0){
        //printf("\np: %f\nn: %f\n", p, n);
        if (x == 0){
            y --;
            points += matrix[x][y];
        } else if (y == 0){
            x --;
            points += matrix[x][y];
        } else if (p / n >= y / (double)(x + y)){
            p -= n * y / (x + y);
            n -= n * y / (x + y);
            points += matrix[x][y];
            x --;
        } else {
            n -= n * x / (x + y);
            points += matrix[x][y];
            y --;
        }
    }
    return points;
}

double c(int n, int k){
    double x = 1.0;
    int i;
    for (i = n; i > (n-k); i--){
        x *= i;
    }
    for (i = 1; i <= k; i++){
        x /= i;
    }
    return x;
}

int numOfPoints(){
    int points = 0;
    int x, y;
    for (x = 0; x < W; x++) {
        for (y = 0; y < W; y++) {
            points += matrix[x][y];
        }
    }
    return points;
}

int main (int argc, const char * argv[])
{
    int n = c(W + H - 2, W - 1);
    printf("%d path(s)",n);
    int maxPoints = numOfPoints() + 1;
    int *countPtr = (int *)calloc(maxPoints, sizeof (int));
    int i;
    for (i = 0; i < n; i++){
        countPtr[path(i, n)]++;
    }
    for (i = 0; i <= maxPoints; i++){
       printf("n° of path(s) with %d point(s) : \t%d\n", i, countPtr[i]);
    }
    free(countPtr);
    return 0;
}