2017-12-05 4 views
0

行列の「島」または行列のすべてを1で区切る関数が必要です。私の例では正常に動作しますが、失敗した場合はいくつかの "特別な"ケースがあります(この例のように)。マトリックスを評価するための再帰関数へのエラーまたは変換コードの修正

このエラーを修正するにはどうすればよいですか?この関数を再帰関数に変換することができます。行列を通って1の位置に移動させ、再帰関数を呼び出して、その周りのすべての点を評価します。例えば

var matrix = [ 
 
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 
    [0, 1, 0, 1, 1, 1, 1, 0, 0, 0], 
 
    [1, 1, 0, 1, 0, 0, 0, 1, 0, 0], 
 
    [1, 0, 0, 1, 0, 0, 0, 1, 0, 0], 
 
    [0, 0, 1, 1, 0, 0, 0, 1, 0, 0], 
 
    [0, 0, 0, 1, 0, 0, 0, 1, 1, 0], 
 
    [0, 1, 0, 1, 0, 0, 0, 1, 1, 1], 
 
    [0, 1, 0, 1, 1, 0, 0, 1, 1, 0], 
 
    [0, 1, 1, 1, 1, 1, 1, 1, 0, 0], 
 
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 
]; 
 

 
var contFilas = matrix.length; 
 
var contColumnas = matrix[0].length; 
 
var canvas = document.querySelector("canvas"); 
 
var ctx = canvas.getContext("2d"); 
 
var sz = 20; 
 
var regions = []; 
 
var regionCollection = []; 
 

 
canvas.width = sz * contColumnas; 
 
canvas.height = sz * contColumnas; 
 
ctx.fillStyle = "silver"; 
 
ctx.fillRect(0, 0, canvas.width, canvas.height); 
 

 
for (var y = 0; y < contFilas; y++) { 
 
    var regionline = []; 
 
    regions.push(regionline); 
 

 
    for (var x = 0; x < contColumnas; x++) { 
 
     var pixelRegion = 0; 
 
     regionline[x] = 0; 
 
     
 

 

 
     if (matrix[y][x] === 1) { 
 
      // check previous row 
 
      if (y) { 
 
       if (matrix[y - 1][x]) { 
 
        pixelRegion = regions[y - 1][x]; 
 
       } else if (x && matrix[y - 1][x - 1]) { 
 
        pixelRegion = regions[y - 1][x - 1]; 
 
       } else if (x + 1 < contColumnas && matrix[y - 1][x + 1]) { 
 
        pixelRegion = regions[y - 1][x + 1]; 
 
       } 
 
      } 
 

 
      // check current row 
 
      if (x && matrix[y][x - 1]) { 
 
       pixelRegion = regions[y][x - 1]; 
 
      } 
 

 
      // if not connected, start a new region 
 
      if (!pixelRegion) { 
 
       regionCollection.push([]); 
 
       pixelRegion = regionCollection.length; 
 
      } 
 
      // remember region 
 
      regionline[x] = pixelRegion; 
 
      regionCollection[pixelRegion - 1].push([x, y]); 
 

 
      // paint it 
 
      ctx.fillStyle = "black"; 
 
      ctx.fillRect(x * sz + 1, y * sz + 1, sz - 2, sz - 2); 
 
     } 
 

 

 
     ctx.fillStyle = "white"; 
 
     ctx.fillText(pixelRegion, x * sz + 8, y * sz + 13); 
 

 
    } 
 
} 
 
document.querySelector("#result").innerHTML = JSON.stringify(regionCollection);
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
 
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
 
    <title>getUserMedia</title> 
 
</head> 
 
<body> 
 
\t <canvas></canvas> 
 
\t <div id="result"></div> 
 
</body> 
 
</html>

、領域2及び3は、唯一の(領域2)でなければなりません。つまり、は2つの異なる領域があります。コードのエラーは何ですか?どうすれば修正できますか?

答えて

0

私はあなたの問題は、実際には(「1回のパス」と数えているかによって)実際にはできない配列の1回のパスでこれを実行しようとしていると思います。

最も簡単なアルゴリズムはおそらくアレイをループすることで、1がフラッドフィル操作を実行することがわかります。フラッドフィルでヒットしたピクセルはすべて領域に格納され、残りのループで無視されます。フラッドフィルは計算上かなり遅いですが、よく理解されており、そこにはたくさんのコードがあります。

既にこのコードがあるとすれば、regionCollectionオブジェクトを持っていて、どの領域に接触しているかを確認するだけで、より高速なソリューションになると思います。もしあれば、それらを組み合わせてください。フラッドフィルを使用するよりも読みにくく、おそらくコードが多いので、最適化したいものに依存します。

関連する問題