簡體   English   中英

從左上角到右下角計算所有可能的路徑

[英]Count all possible paths from top left to bottom right

任務是計算從 mXn 矩陣的左上角到右下角的所有可能路徑,其約束條件是從每個單元格只能向右或向下移動。

     int[][] count = new int[n][m];
     int i,j;

     for (i = 0; i < n; i++)
         count[i][0] = 1;
     for (i = 0; i < m; i++)
         count[0][i] = 1;

     for (i = 1; i < n; i++)
         for (j = 1; j < m; j++)
             count[i][j] = (count[i - 1][j] + count[i][j - 1]);

     System.out.println(count[n - 1][m - 1]);

上面的代碼顯示了較大的 m 和 n 值的錯誤答案。 使用長數組也不起作用。 在正確的解決方案之一中,公式`count[i][j]=(count[i-1][j]+count[i][j-1])%( (int)Math.pow(10, 9)+7) 用來! 我無法理解相同的原因。

使用正方形大小進行測試並使用int ,您最多可以計算出 17x17。 使用 18x18,您會得到數字溢出。

要檢測數字溢出,請更改以下行:

count[i][j] = (count[i - 1][j] + count[i][j - 1]);

到:

count[i][j] = Math.addExact(count[i - 1][j], count[i][j - 1]);

以 18x18 運行,你會得到java.lang.ArithmeticException: integer overflow ,而601080390打印601080390

更改為long會將限制提高到 34x34 = 7219428434016265740 ,並且 35x35 失敗。

要超越這一點,請使用BigInteger

private static void count(int n, int m) {
    BigInteger[][] count = new BigInteger[n][m];
    for (int i = 0; i < n; i++)
        count[i][0] = BigInteger.ONE;
    for (int i = 0; i < m; i++)
        count[0][i] = BigInteger.ONE;
    for (int i = 1; i < n; i++)
        for (int j = 1; j < m; j++)
            count[i][j] = count[i - 1][j].add(count[i][j - 1]);
    System.out.println(n + "x" + m + ": " + count[n - 1][m - 1]);
}

您現在可以計算非常大的尺寸:

public static void main(String[] args) {
    for (int i = 10; i < 150; i+=10)
        count(i,i);
}

輸出

10x10: 48620
20x20: 35345263800
30x30: 30067266499541040
40x40: 27217014869199032015600
50x50: 25477612258980856902730428600
60x60: 24356699707654619143838606602026720
70x70: 23623985175715118288974865541854103729000
80x80: 23156006494021191956342707682359261381151378400
90x90: 22880174247360071687155809670095748237789263482394000
100x100: 22750883079422934966181954039568885395604168260154104734000
110x110: 22738029575969641265497648088901902565550598643635116137437818400
120x120: 22820983692956015651850538861400483591556161461874723704379950728024000
130x130: 22985198722890636106807214387141205118592781510195606858610359655612113472140
140x140: 23220197341838572012462842682887166477737842005968501197039194284526789533662125200

從 mxn 網格的左上角到右下角僅通過向右和向下的步驟需要 m + n - 2 步:m - 1 步向右,n - 1 步向下。 每條不同的路徑都有一個特定的選擇,即哪些步驟是向下的(相當於:哪些步驟是正確的)。 有一個分析解決方案:

factorial(m + n - 2) / (factorial(m - 1) * factorial(n - 1))

你可以識別出作為m-1個m階+n二項式系數- 2。

當然,您不需要那樣計算它,事實上,如果您想這樣做,您需要非常小心,因為階乘增長得非常快。 這就是我提出它的原因:無論你用什么方法計算它,結果在 m 接近 n 時迅速增長,很快超過long的范圍——盡管是指數級的,而不是階乘的。

在正確的解決方案之一中,公式`count[i][j]=(count[i-1][j]+count[i][j-1])%((int)Math.pow(10, 9)+7); 用來! 我無法理解相同的原因。

這不會用於您提出的問題的正確解決方案,但我已經看到了這個問題的修改版本,它是有意義的:一個要求您計算結果模 1000000007 ,這正是位這讓你感到困惑。 我想我已經在 Project Euler 上看到過,但也可能在其他地方。 該問題的這種變化允許人們在任何具有 32 位整數類型的系統上完全避免不可表示的整數問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM