आगे सोचा के बाद, मैं एक तेजी से समाधान के साथ आ गया है:
साथ StartX
, StartY
, और EndY
गुण अपरिवर्तनीय Range
struct बनाएँ।
वर्तमान Range
एस की एक स्पैस सरणी बनाए रखें, छवि की ऊंचाई के बराबर लंबाई के साथ, और एक एकल शून्य वर्तमान रेंज चर।
- : यह सरणी स्तंभ में प्रत्येक कक्ष के लिए
- साफ़
currentRange
, रेंज शामिल यदि कोई हो, कि प्रत्येक Y पर शुरू होता है समन्वय
प्रत्येक कॉलम के लिए होगा,
यदि कोई मौजूदा श्रेणी नहीं है, या यदि वहां है लेकिन यह इस सेल (यदि currentRange.EndY <= y
) से पहले समाप्त हो गया है, तो श्रेणी रेंज में y
'वें तत्व पर वर्तमान रेंज सेट करें।
इस प्रकार, currentRange
वर्तमान सेल में मौजूद सीमा को संदर्भित करेगा, या वर्तमान सेल, या null
यदि वर्तमान सेल किसी सीमा में नहीं है।
वर्तमान सेल 1
है:
हम एक सीमा में कर रहे हैं, कुछ भी नहीं – रेंज अगले कॉलम में जारी कर दिया जाए।
हम एक श्रेणी में नहीं हैं, तो स्तंभ नीचे पाश जब तक हम एक 0
या एक स्तंभ के अंत में, तो एक नई रेंज 1
से खींच बनाने के हम सिर्फ पाश के अंत तक पाया मारा।
फिर, आगे बढ़ें यदि (वर्तमान सेल अब 0
या कॉलम के अंत में है, और हम एक सीमा में नहीं हैं)
यदि आप मौजूदा सीमा को दबाते हैं तो आप नई सीमा बनाने के लिए आगे बढ़ते हैं , आप या तो नई रेंज को रोक सकते हैं और मौजूदा रेंज को नीचे रख सकते हैं (फजी किनारों के लिए सबसे अच्छा), या मौजूदा रेंज को बंद करें (नीचे देखें) और मौजूदा रेंज से नई सीमा को नीचे ले जाने दें।
- वर्तमान सेल
0
यह है:
- हम एक सीमा में कर रहे हैं, सीमा बंद:
- वापसी एक नए आयत रेंज की आरंभ एक्स और वाई वर्तमान Y तक खींच और सीमा का अंत एक्स
- सक्रिय श्रेणियों की सरणी से सीमा साफ़ करें।
इस एल्गोरिथ्म गणना में O(x * y)
और अंतरिक्ष में O(y)
है। मेरा मानना है कि यह समस्या का सबसे तेज़ समाधान है।
आप इस एल्गोरिदम को घुमा सकते हैं और कॉलम के बजाए पंक्तियों को स्कैन कर सकते हैं (ताकि सीमाएं दाएं की बजाय नीचे की ओर फैली हों), जो भंडारण में O(x)
होगी।
class BoxFinder {
class Range {
public Range(int startX, int startY, int endY) {
StartX = startX;
StartY = startY;
EndY = endY;
}
public int StartX { get; private set; }
public int StartY { get; private set; }
public int EndY { get; private set; }
}
public BoxFinder(int[,] data) {
Data = data;
Width = data.GetLength(0);
Height = data.GetLength(1);
ranges = new Range[Height];
}
public int[,] Data { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; }
private Range[] ranges;
public IEnumerable<Rectangle> GetBoxes() {
for (int x = 0; x < Width; x++) {
Range currentRange = null;
for (int y = 0; y < Height; y++) {
Func<Range, Rectangle> CloseRange = r => {
currentRange = null;
ranges[r.StartY] = null;
return new Rectangle(
r.StartY,
r.StartX,
x - r.StartX,
r.EndY - r.StartY
);
};
if (currentRange == null || currentRange.EndY <= y)
currentRange = ranges[y];
if (Data[x, y] == 1) {
if (currentRange == null) {
int startY = y;
for (; y < Height && Data[x, y] == 1; y++) {
if (ranges[y] != null)
yield return CloseRange(ranges[y]);
//If there are fuzzy edges, break; instead
}
ranges[startY] = new Range(x, startY, y);
if (y == Height)
continue;
//Otherwise, continue to the next if in case a previous range just ended
}
}
//No else; we can get here after creating a range
if(Data[x, y] == 0) {
if (currentRange != null)
yield return CloseRange(currentRange);
}
}
}
}
}
क्या आप उन्हें _from_ गणना कर रहे हैं:
यहाँ एक सी # कार्यान्वयन है? आपके पास क्या डेटा है? – SLaks
एक 2 डी-सरणी से: http://makerland.de/array।txt – EnemyArea
यह प्रश्न थोड़ा सा व्यापक है, आपने पहले से क्या किया है, आपने क्या प्रयास किया है, क्या आपके पास कोई उदाहरण कोड है? – thedaian