C#练习题答案: 矩形覆盖的总面积【难度:5级】--景越C#经典编程题库,1000道C#基础练习题等你来挑战

这篇博客提供了10种不同的解答方法,针对C#编程中的一个经典几何逻辑题目——矩形覆盖的总面积问题。难度级别为5级,适合C#初学者和进阶者进行编程练习和面试准备。
摘要由CSDN通过智能技术生成

矩形覆盖的总面积【难度:5级】:

答案1:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Solution
{
    public static class Kata
    {

       private class Rectangle
        {
            public long x0;
            public long y0;
            public long x1;
            public long y1;
            public bool ToDelete = false;

            public Rectangle(long x0, long y0, long x1, long y1)
            {
                this.x0 = x0;
                this.x1 = x1;
                this.y0 = y0;
                this.y1 = y1;
            }
            public long S()
            {
                return (x1 - x0) * (y1 - y0);
            }

            public bool IsInside(Rectangle r)
            {
                return ((r.x0 >= x0) &amp;&amp; (r.x1 <= x1) &amp;&amp; (r.y0 >= y0) &amp;&amp; (r.y1 <= y1)) ? true : false;
            }

            public bool IsOutside(Rectangle r)
            {
                return ((r.x0 >= x1) || (r.x1 <= x0) || (r.y0 >= y1) || (r.y1 <= y0)) ? true : false;
            }

            public List<Rectangle> GetIntersection(Rectangle r)
            {
                List<Rectangle> rests = new List<Rectangle>();
                if (r.x0 < x0)
                    rests.Add(new Rectangle(r.x0, r.y0, x0, r.y1));
                if (r.x1 > x1)
                    rests.Add(new Rectangle(x1, r.y0, r.x1, r.y1));
                if (r.y0 < y0)
                    rests.Add(new Rectangle(Math.Max(r.x0, x0), r.y0, Math.Min(r.x1, x1), y0));
                if (r.y1 > y1)
                    rests.Add(new Rectangle(Math.Max(r.x0, x0), y1, Math.Min(r.x1, x1), r.y1));
                return rests;
            }

        }

        public static long Calculate(IEnumerable<int[]> rectangles)
        {
            long maxS = 0;
            List<Rectangle> lastRectangle = new List<Rectangle>(rectangles.Select(x => new Rectangle((long)x[0], (long)x[1], (long)x[2], (long)x[3])));
            while (lastRectangle.Count > 0)
            {
                Rectangle top = lastRectangle.First();
                lastRectangle.Remove(top);
                List<Rectangle> intersect = new List<Rectangle>() { top };
                var intersected = lastRectangle.Where(x => !x.IsOutside(top));
                foreach (Rectangle r in intersected)
                {
                    intersect.RemoveAll(x => r.IsInside(x));
                    List<Rectangle> newIntersections = new List<Rectangle>();
                    foreach (Rectangle x in intersect)
                        if (!r.IsOutside(x))
                        {
                            newIntersections.AddRange(r.GetIntersection(x));
                            x.ToDelete = true;
                        }
                    intersect.RemoveAll(x => x.ToDelete);
                    intersect.AddRange(newIntersections);
                    if (intersect.Count == 0)
                        break;
                }
                if (intersect.Count>0)
                    maxS += intersect.Sum(x =>x.S());
            }
            return maxS;
        }
    }
}

答案2:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;

namespace Solution
{
  public class Kata
  {
    public static long Calculate(IEnumerable<int[]> rectangles)
    {            
        if (rectangles.Count() == 0) return 0;
        return new Kata().rectangleArea(rectangles.ToArray());
    }

    public long rectangleArea(int[][] rectangles)
    {
        int OPEN = 1, CLOSE = -1;
        int[][] events = new int[rectangles.Length * 2][];
        HashSet<int> Xvals = new HashSet<int>();
        int t = 0;
        foreach (int[] rec in rectangles)
        {
            events[t++] = new int[] { rec[1], OPEN, rec[0], rec[2] };
            events[t++] = new int[] { rec[3], CLOSE, rec[0], rec[2] };
            Xvals.Add(rec[0]);
            Xvals.Add(rec[2]);
        }

        //Array.Sort(events, (a, b) => a[0] > b[0]);
        events = events.OrderBy(rect => rect[0]).ToArray();

        int[] X = Xvals.ToArray();
        Array.Sort(X);
        Dictionary<int, int> Xi = new Dictionary<int, int>();
        for (int i = 0; i < X.Length; ++i)
            Xi.Add(X[i], i);

        Node active = new Node(0, X.Length - 1, X);
        long ans = 0;
        long cur_x_sum = 0;
        int cur_y = events[0][0];

        foreach (int[] even in events)
        {
            int y = even[0], typ = even[1], x1 = even[2], x2 = even[3];
            ans += cur_x_sum * (y - cur_y);
            cur_x_sum = active.update(Xi[x1], Xi[x2], typ);
            cur_y = y;
        }

        return ans;
    }

    class Node
    {
        int start, end;
        int[] X;
        Node left, right;
        int count;
        long total;

        public Node(int start, int end, int[] X)
        {
            this.start = start;
            this.end = end;
            this.X = X;
            left = null;
            right = null;
            count = 0;
            total = 0;
        }

        public int getRangeMid()
        {
            return start + (end - start) / 2;
        }

        public Node getLeft()
        {
            if (left == null) left = new Node(start, getRangeMid(), X);
            return left;
        }

        public Node getRight()
        {
            if (right == null) right = new Node(getRangeMid(), end, X);
            return right;
        }

        public long update(int i, int j, int val)
        {
            if (i >= j) return 0;
            if (start == i &amp;&amp; end == j)
            {
                count += val;
            }
            else
            {
                getLeft().update(i, Math.Min(getRangeMid(), j), val);
                getRight().update(Math.Max(getRangeMid(), i), j, val);
            }

            if (count > 0) total = X[end] - X[start];
            else total = getLeft().total + getRight().total;

            return total;
        }
    }
  }
}

答案3:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Solution
{
  public static class Kata
  {
    struct Rect
        {
            public int xMin, yMin, xMax, yMax;

            public Rect(int xMin, int yMin, int xMax, int yMax)
            {
                this.xMin = xMin;
                this.xMax = xMax;
                this.yMin = yMin;
                this.yMax = yMax;
            }

            public long Area()
            {
                int w = xMax - xMin;
                int h = yMax - yMin;
                if (w < 0 || h < 0)
                    return 0;
                return (long)w * (long)h;
            }

        }
        
        public static long Calculate(IEnumerable<int[]> rectsEnum)
        {
            var rects = rectsEnum
                .Where(r => r[2] > r[0] &amp;&amp; r[3] > r[1])
                .Select(r =>
                 new Rect(r[0], r[1], r[2], r[3]))
                 .ToList();
            rects.Sort((r1,r2)=>r1.xMin.CompareTo(r2.xMin));

            long sum = 0;

            for (int i = 0; i < rects.Count; i++)
            {
                var rect = rects[i];

                int maxX = rects[i].xMax;

                // what is left of rect we are inserting
                var toInsert = new List<Rect>();
                toInsert.Add(rects[i]);


                // substract other rects (from original list)
                for (int j = i + 1; j < rects.Count; j++)
                {
                    var rMinus = rects[j];

                    if (rMinus.xMin >= maxX)
                        break;

                    if (rect.xMin >= rMinus.xMax
                     || rect.xMax <= rMinus.xMin
                     || rect.yMin >= rMinus.yMax
                     || rect.yMax <= rMinus.yMin)
                        continue;

                    // substracting creates new rects, so iterate generations                                        
                    int toInsertOldCount = toInsert.Count;
                    for (int k = 0; k < toInsertOldCount; k++)
                    {
                        var rPlus = toInsert[k];

                        if (   rPlus.xMin >= rMinus.xMax
                            || rPlus.xMax <= rMinus.xMin
                            || rPlus.yMin >= rMinus.yMax
                            || rPlus.yMax <= rMinus.yMin)
                            continue;
                        
                        // refine by replacing rPlus with rPlus - rMinus
                        toInsert.RemoveAt(k);
                        toInsertOldCount--;
                        k--;                            

                        // divide plus into upto 4 sections
                        if (rPlus.xMin < rMinus.xMin)
                        { // middle left side
                            toInsert.Add(new Rect(
                                rPlus.xMin,
                                Math.Max(rPlus.yMin, rMinus.yMin),
                                rMinus.xMin,
                                Math.Min(rPlus.yMax, rMinus.yMax)));
                        }
                        if (rPlus.xMax > rMinus.xMax)
                        {  // middle right side
                            toInsert.Add(new Rect(
                                rMinus.xMax,
                                Math.Max(rPlus.yMin, rMinus.yMin),
                                rPlus.xMax,
                                Math.Min(rPlus.yMax, rMinus.yMax)));
                        }
                        if (rPlus.yMin < rMinus.yMin)
                        {  // top
                            toInsert.Add(new Rect(
                                rPlus.xMin,
                                rPlus.yMin,
                                rPlus.xMax,
                                rMinus.yMin));
                        }
                        if (rPlus.yMax > rMinus.yMax)
                        {  // bottom
                            toInsert.Add(new Rect(
                                rPlus.xMin,
                                rMinus.yMax,
                                rPlus.xMax,
                                rPlus.yMax));
                        }                        
                    }
                    // nothing left to insert, early exit
                    if (toInsert.Count == 0)
                        break;

                }

                foreach (var rPlus in toInsert)
                    sum += rPlus.Area();
            }

            return sum;
        }
  }
}

答案4:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Solution
{
  public static class Kata
  {
        struct Rect
        {
            public int x0,y0,x1,y1;            

            public static int Comparison(Rect r1, Rect r2)
            {
                int r;
                r = r1.x0.CompareTo(r2.x0);
                if (r != 0) return r;
                r = r1.y0.CompareTo(r2.y0);
                if (r != 0) return r;
                r = r1.x1.CompareTo(r2.x1);
                if (r != 0) return r;
                r = r1.y1.CompareTo(r2.y1);
                return r;
            }

            public long Area()
            {
                int w = x1 - x0;
                int h = y1 - y0;
                if (w < 0 || h < 0)
                    return 0;
                return (long)w * (long)h;
            }

            public bool IsEqual(in Rect other)
            {
                return x0 == other.x0
                    &amp;&amp; y0 == other.y0
                    &amp;&amp; x1 == other.x1
                    &amp;&amp; y1 == other.y1;
            }

            public Rect Intersect(in Rect other)
            {
                return new Rect
                {
                    x0 = Math.Max(x0,other.x0),
                    y0 = Math.Max(y0, other.y0),
                    x1 = Math.Min(x1, other.x1),
                    y1 = Math.Min(y1, other.y1),
                };                
            }
        }

        public static long Calculate(IEnumerable<int[]> rectsEnum)
        {
            var rects = rectsEnum.Select(r=> 
                new Rect { 
                    x0 = r[0], 
                    y0 = r[1],
                    x1 = r[2],
                    y1 = r[3] })
                .ToList();
            rects.Sort(Rect.Comparison);
            return CalculateSorted(rects);
        }

        static long CalculateSorted(List<Rect> rects)
        {
            for (int i = 1; i < rects.Count; i++)
            {
                if (rects[i].IsEqual(rects[i - 1]))
                {
                    rects.RemoveAt(i);
                    i--;
                }
            }

            long sum = 0;
            for (int i = 0; i < rects.Count; i++)
            {
                List<Rect> localIntersections = null; ;

                var area = rects[i].Area();
                var skip = false;
                for (int j = i + 1; j < rects.Count; j++)
                {

                    if (rects[j].x0 > rects[i].x1)
                        break;

                    var intersection = rects[i].Intersect( rects[j]);
                    var intersectionArea = intersection.Area();
                    if (intersectionArea == area)
                    {
                        skip = true;
                        break;
                    }
                    if (intersectionArea > 0)
                    {
                        if (localIntersections == null)
                            localIntersections = new List<Rect>();
                        localIntersections.Add(intersection);
                    }
                }
                if (skip)
                    continue;
                sum += area;
                if (localIntersections != null)
                    sum -= CalculateSorted(localIntersections);
            }

            return sum;
        }
  }
}

答案5:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Solution
{
  public static class Kata
  {
     public static long Calculate(this IEnumerable<int[]> rectangles)
        {
            var rectangleList = rectangles.Select(item => (int[]) item.Clone()).ToList();

            for (var i = 0; i < rectangleList.Count - 1; i++)
            {
                var rectangleI = rectangleList[i];
                if (rectangleI == null)
                {
                    continue;
                }

                for (var j = i + 1; j < rectangleList.Count; j++)
                {
                    var rectangleJ = rectangleList[j];
                    if (!IsCollision(rectangleI, rectangleJ))
                    {
                        continue;
                    }

                    if (IsIncluding(rectangleI, rectangleJ))
                    {
                        rectangleList[j] = null;
                        continue;
                    }

                    if (IsIncluding(rectangleJ, rectangleI))
                    {
                        rectangleList[i] = null;
                        break;
                    }

                    if (IsSideIntersection(rectangleI, rectangleJ) || IsSideIntersection(rectangleJ, rectangleI))
                    {
                        continue;
                    }

                    if (IsCross(rectangleI, rectangleJ))
                    {
                        rectangleList.AddRange(new[] {new[] {rectangleJ[0], rectangleI[3], rectangleJ[2], rectangleJ[3]}});
                        rectangleJ[3] = rectangleI[1];
                        continue;
                    }

                    if (IsCross(rectangleJ, rectangleI))
                    {
                        rectangleList.AddRange(new[] {new[] {rectangleI[0], rectangleJ[3], rectangleI[2], rectangleI[3]}});
                        rectangleI[3] = rectangleJ[1];
                        continue;
                    }

                    var rectangle = CreateCornerIntersection(rectangleI, rectangleJ);
                    if (rectangle != null)
                    {
                        rectangleList.AddRange(new []{ rectangle });
                        continue;
                    }

                    rectangle = CreateCornerIntersection(rectangleJ, rectangleI);
                    if (rectangle != null)
                    {
                        rectangleList.AddRange(new[] { rectangle });
                    }
                }
            }

            double result = 0;
            foreach (var rectangle in rectangleList)
            {
                if (rectangle != null)
                {
                    result += (double) ((double) rectangle[2] - (double) rectangle[0]) *
                              ((double) rectangle[3] - (double) rectangle[1]);
                }
            }
            return Convert.ToInt64(result);
        }

        private static bool IsCollision(int[] rectangleA, int[] rectangleB)
        {
            return rectangleA != null &amp;&amp; rectangleB != null &amp;&amp;
                   !(rectangleA[2] <= rectangleB[0] || rectangleA[0] >= rectangleB[2] ||
                     rectangleA[3] <= rectangleB[1] || rectangleA[1] > rectangleB[3]);
        }

        private static bool IsIncluding(int[] rectangleA, int[] rectangleB)
        {
            return rectangleA[0] <= rectangleB[0] &amp;&amp; rectangleA[1] <= rectangleB[1] &amp;&amp; rectangleA[2] >= rectangleB[2] &amp;&amp;
                   rectangleA[3] >= rectangleB[3];
        }

        private static bool IsSideIntersection(int[] rectangleA, int[] rectangleB)
        {
            if (rectangleA[0] < rectangleB[0] &amp;&amp; rectangleA[2] > rectangleB[0] &amp;&amp; rectangleA[2] <= rectangleB[2] &amp;&amp;
                rectangleA[1] >= rectangleB[1] &amp;&amp; rectangleA[3] <= rectangleB[3])
            {
                rectangleA[2] = rectangleB[0];
                return true;
            }

            if (rectangleA[0] < rectangleB[2] &amp;&amp; rectangleA[2] > rectangleB[2] &amp;&amp; rectangleA[0] >= rectangleB[0] &amp;&amp;
                rectangleA[1] >= rectangleB[1] &amp;&amp; rectangleA[3] <= rectangleB[3])
            {
                rectangleA[0] = rectangleB[2];
                return true;
            }

            if (rectangleA[1] < rectangleB[1] &amp;&amp; rectangleA[3] > rectangleB[1] &amp;&amp; rectangleA[3] <= rectangleB[3] &amp;&amp;
                rectangleA[0] >= rectangleB[0] &amp;&amp; rectangleA[2] <= rectangleB[2])
            {
                rectangleA[3] = rectangleB[1];
                return true;
            }

            if (rectangleA[1] < rectangleB[3] &amp;&amp; rectangleA[3] > rectangleB[3] &amp;&amp; rectangleA[1] >= rectangleB[1] &amp;&amp;
                rectangleA[0] >= rectangleB[0] &amp;&amp; rectangleA[2] <= rectangleB[2])
            {
                rectangleA[1] = rectangleB[3];
                return true;
            }

            return false;
        }

        private static bool IsCross(int[] rectangleA, int[] rectangleB)
        {
            return rectangleA[0] < rectangleB[0] &amp;&amp; rectangleA[2] > rectangleB[2] &amp;&amp; rectangleA[1] > rectangleB[1] &amp;&amp;
                   rectangleA[3] < rectangleB[3];
        }

        private static int[] CreateCornerIntersection(int[] rectangleA, int[] rectangleB)
        {
            if (rectangleA[0] < rectangleB[0] &amp;&amp; rectangleA[2] > rectangleB[0] &amp;&amp; rectangleA[2] < rectangleB[2] &amp;&amp;
                rectangleA[1] < rectangleB[1] &amp;&amp; rectangleA[3] > rectangleB[1] &amp;&amp; rectangleA[3] < rectangleB[3])
            {
                var rectangle = new[] {rectangleA[0], rectangleB[1], rectangleB[0], rectangleA[3]};
                rectangleA[3] = rectangleB[1];
                return rectangle;
            }

            if (rectangleA[0] < rectangleB[0] &amp;&amp; rectangleA[2] > rectangleB[0] &amp;&amp; rectangleA[2] < rectangleB[2] &amp;&amp;
                rectangleA[1] < rectangleB[3] &amp;&amp; rectangleA[3] > rectangleB[3])
            {
                var rectangle = new[] {rectangleA[0], rectangleA[1], rectangleB[0], rectangleB[3]};
                rectangleA[1] = rectangleB[3];
                return rectangle;
            }

            return null;
        } 
  }
}

答案6:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Solution
{
  public static class Kata
  {
    public static long Calculate(IEnumerable<int[]> rectangles)
    {
      if (!rectangles.Any()) return 0;
      rectangles = rectangles.OrderBy(r => r[0]).ToList();
      var xs = rectangles.Select(r=>r[0]).Concat(rectangles.Select(r=>r[2])).Distinct().OrderBy(x=>x).ToList();
      var scan = new List<int[]>();    
      // long recIndex = 0;
      long area = 0;
      long scanLeft = xs[0];
      xs.RemoveAt(0);
      using(var recsEnum = rectangles.GetEnumerator())
      {
        bool hasMoreRec = recsEnum.MoveNext();
        
        xs.ForEach(scanRight =>
        {
          // add rectangles to scan that align on scan left...
          for(;hasMoreRec &amp;&amp; recsEnum.Current[0] == scanLeft; hasMoreRec = recsEnum.MoveNext())
          {
            scan.Add(recsEnum.Current);
          }
          
          scan.Sort((a,b) => a[1] - b[1]); // order by top
          long height = 0;
          long lastY = long.MinValue; // last y accounted for in height
          scan.ForEach(s =>
          {
            long top = s[1];
            long bottom = s[3];
            if (lastY < bottom) // overlaps, add height of overlapping portion
            {
              height += bottom - Math.Max(lastY, top);
              lastY = bottom;
            }
          });
          
          // area of rectangles that overlap scan: height * width
          area += height * (scanRight - scanLeft);
            
          // proceding left-to-right, so remove the scan rectangles whose right-side is to the left of current scan
          scan.RemoveAll(r=>r[2] <= scanRight);
          scanLeft = scanRight;
        });
      }
      
      return area;
    }
  }
}

答案7:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Solution
{
using System;
using System.Collections.Generic;
using System.Linq;

public class Rect
{
    public long x0;
    public long x1;
    public long y0;
    public long y1;
    public bool ToDelete { get; internal set; }

    public Rect(long left, long top, long right, long bottom)
    {
        x0 = left;
        x1 = right;
        y0 = top;
        y1 = bottom;
    }

    public long Area()
    {
        return (x1 - x0) * (y1 - y0);
    }

    public bool IsInside(Rect other)
    {
        return ((other.x0  >= x0) &amp;&amp; (other.x1 <= x1) &amp;&amp; (other.y0 >= y0) &amp;&amp; (other.y1 <= y1)); 
    }

    public bool IsOutside(Rect other)
    {
        return ((other.x0 >= x1) || (other.x1 <= x0) || (other.y0 >= y1) || (other.y1 <= y0));
    }

    internal IEnumerable<Rect> GetIntersection(Rect r)
    {
        List<Rect> newRects = new List<Rect>();

        if (r.x0 < x0)
        {
            newRects.Add(new Rect(r.x0,r.y0,x0,r.y1));
        }

        if (r.x1 > x1)
        {
            newRects.Add(new Rect(x1, r.y0, r.x1, r.y1));
        }

        if (r.y0 < y0)
        {
            newRects.Add(new Rect(Math.Max(r.x0, x0), r.y0, Math.Min(r.x1, x1), y0));
        }

        if (r.y1 > y1)
        {
            newRects.Add(new Rect(Math.Max(r.x0, x0), y1, Math.Min(r.x1, x1), r.y1));
        }

        return newRects;
    }
}

public static class Kata
{
    public static long Calculate(IEnumerable<int[]> rectangles)
    {
        long area = 0;
        List<Rect> originals = new List<Rect>(rectangles.Select(x => new Rect(
            (long)x[0],(long)x[1],(long)x[2],(long)x[3])));

        while (originals.Count > 0)
        {
            Rect top = originals.First();
            List<Rect> workingSet = new List<Rect> { top };
            originals.Remove(top);

            var intersections = originals.Where(x => !x.IsOutside(top));
            foreach (var i in intersections)
            {
                workingSet.RemoveAll(x => i.IsInside(x));

                List<Rect> newRects = new List<Rect>();
                foreach (var r in workingSet)
                {
                    if (!(i.IsOutside(r)))
                    {
                        newRects.AddRange(i.GetIntersection(r));
                        r.ToDelete = true;
                    }
                }

                workingSet.RemoveAll(x => x.ToDelete);
                workingSet.AddRange(newRects);

                if (workingSet.Count == 0)
                    break;
            }
            
            if (workingSet.Count > 0)
            {
                area += workingSet.Sum(x => x.Area());
            }
        }

        return area;
    }

    static void Main(string[] args)
    {
        Calculate(new[] { new[] { 0, 0, 1, 1 }, new[] { 1, 1, 2, 2 } });
        Console.WriteLine("Done!");
        Console.ReadKey();
    }
}
}

答案8:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Solution
{
   public static class Kata
    {
        public class Square
        {
            public long S { get; set;}
            public long X0 { get; set;}
            public long X1 { get; set; }
            public long Y0 { get; set; }
            public long Y1 { get; set; }

            public Square(long[] rect)
            {
                X0 = rect[0];
                Y0 = rect[1];
                X1 = rect[2];
                Y1 = rect[3];
                S = (X1-X0)* (Y1-Y0);
            }

            public Square(int[] rect)
            {
                X0 = rect[0];
                Y0 = rect[1];
                X1 = rect[2];
                Y1 = rect[3];
                S = (X1 - X0) * (Y1 - Y0);
            }
        }

        private static HashSet<Square> _squares;

        private static Square Intersection(Square s1, Square s2)
        {
           
            var xarr = (new List<long> { s1.X0, s1.X1, s2.X0, s2.X1}).OrderBy(v => v).ToList();
            var yarr = (new List<long> { s1.Y0, s1.Y1, s2.Y0, s2.Y1 }).OrderBy(v => v).ToList();
            var x0 = xarr[1];
            var x1 = xarr[2];
            var y0 = yarr[1];
            var y1 = yarr[2];

            
            var sq = new Square(new [] { x0,y0,x1,y1});
            var k1 = s1.S > 0;
            var k2 = s2.S > 0;
            var k = k1^k2;
            if (!(k1^k2))
                sq.S = -1*sq.S;
            return sq;
        }

        public static void AddSquare(Square s)
        {
            bool add = true;
            var sqToDel = new HashSet<Square>();
            var sqToAdd = new HashSet<Square>();
           
            foreach (var sq in _squares)
            {
                if (s.X1 <= sq.X0 || s.X0 >= sq.X1 || s.Y1 <= sq.Y0 || s.Y0 >= sq.Y1 )
                    continue;
                if(s.X0 >= sq.X0 &amp;&amp; s.X1 <= sq.X1 &amp;&amp; s.Y0 >= sq.Y0 &amp;&amp; s.Y1 <= sq.Y1)
                {
                    add = false;
                    break;
                }
                if (sq.X0 >= s.X0 &amp;&amp; sq.X1 <= s.X1 &amp;&amp; sq.Y0 >= s.Y0 &amp;&amp; sq.Y1 <= s.Y1)
                {
                    //using (System.IO.StreamWriter file =new System.IO.StreamWriter(@"C:\vs17_projects\CodeWars\Kata\WriteLines2.txt", true))
                    //{
                    //    file.WriteLine("del (" + string.Join(",", new[] { s.X0, s.Y0, s.X1, s.Y1, s.S }) + "),(" + string.Join(",", new[] { sq.X0, sq.Y0, sq.X1, sq.Y1,sq.S }) + ")");
                    //}
                    sqToDel.Add(sq);                   
                    continue;
                }
                var sToAdd = Intersection(s, sq);
                //using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\vs17_projects\CodeWars\Kata\WriteLines2.txt", true))
                //{
                //    file.WriteLine("new (" + string.Join(",", new[] { s.X0, s.Y0, s.X1, s.Y1,s.S }) + "),(" + string.Join(",", new[] { sq.X0, sq.Y0, sq.X1, sq.Y1, sq.S }) + "),(" + string.Join(",", new[] { sToAdd.X0, sToAdd.Y0, sToAdd.X1, sToAdd.Y1, sToAdd.S }) + ")");
                //}
                sqToAdd.Add(sToAdd);
            }
            if (add)
            {
                foreach (var sq in sqToDel)
                {
                    _squares.Remove(sq);
                }
                foreach (var sq in sqToAdd)
                {             
                    _squares.Add(sq);
                }            
                //using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\vs17_projects\CodeWars\Kata\WriteLines2.txt", true))
                //{
                //    file.WriteLine("add (" + string.Join(",", new[] { s.X0, s.Y0, s.X1, s.Y1, s.S }) + ")");
                //}
                _squares.Add(s);
            }          
        }
        public static long Calculate(IEnumerable<int[]> rectangles)
        {
          //  using (System.IO.StreamWriter file =
          //new System.IO.StreamWriter(@"C:\vs17_projects\CodeWars\Kata\WriteLines2.txt", false))
          //  {                
          //  }
            _squares = new HashSet<Square>();
            foreach(var rect in rectangles)
            {
                AddSquare(new Square(rect));
            }
            long res = 0;
            foreach(var sq in _squares)
            {
                res += sq.S;
            }
           return res;
        }
    }
    
}

答案9:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Solution
{
  public static class Kata
  {
    //full_list is a list of top-tier rectangles.  As we add more rectangles,
    // if there are overlaps, we will create "super rectangles" that are
    // larger rectangles containing rectangles within it's area.
    // This will keep the algorythm efficient by not having to
    // compare the current rectangle to every rectangle previously
    // encountered.
    //We will eventually end up with a hyerarchy of super rectangles.
    public static List<Rect> full_list;
    public static long full_size;
    public static bool debug;
    public static long Calculate(IEnumerable<int[]> rectangles)
    {
      full_list = new List<Rect>();
      full_size = 0;
      debug = false;
      foreach (int[] i in rectangles)
      {
         Rect r = new Rect(i[0],i[1],i[2],i[3],true);
        AddNewRect(r);
      }
      return full_size;
    }
    
    //We have a new Rectangle and we want to add it to our list
    // and gather the new amount it adds
    public static void AddNewRect(Rect r)
    {
      List<Rect> intersect_list;
      long size = 0;   
      intersect_list = GetAllTopIntersects(r);  

      //If it doesn't intersect with anything, just add it
      if (intersect_list.Count == 0)
      {
        full_list.Add(r);
        size = r.Size();
        full_size += size;
        return;
      }
      
      //If it intersects with only 1, we only need a larger rectangle if they are
      // both base rectangles
      if (intersect_list.Count == 1)
      {
        Rect intersecting = intersect_list[0];
        
        if (intersecting.isbase &amp;&amp; intersecting.Contains(r)) return; //this rectangle contains nothing new
        
        if (!intersecting.isbase)
        {
          intersecting.SmashThis(r);
          size = r.Size();
          if (size == 0) return;
          full_size += size;
          intersecting.Add(r);
          return;
        }
      }
      //If we get here, either there are multiple intersects or an intersect with a base rectangle
      //either way, a new super rectangle is needed unless we junk this rectangle
      foreach (Rect intersecting in intersect_list)
        intersecting.SmashThis(r);
      size = r.Size();
      if (size == 0) return;
      full_size += size;
      Rect super = new Rect(r);
      foreach(Rect intersecting in intersect_list)
      {
        full_list.Remove(intersecting);
        super.Add(intersecting);
      }
      full_list.Add(super);
    }
    
    //We have a new Rectangle and we want a list of all current
    // rectangles it intersects with;
    public static List<Rect> GetAllTopIntersects(Rect r)
    {
      List<Rect> result = new List<Rect>();
      foreach (Rect top in full_list)
      {
        if (top.Intersects(r))
          result.Add(top);
      }
      return result;
    }
  } //end of Kata class
  
  
  public class Rect
  {
    public int _x0, _x1, _y0, _y1;
    private List<Rect> subrecs;
    public bool isbase;

    public Rect(int x0, int y0, int x1, int y1, bool is_base = false)
    {
      _x0 = x0; _y0 = y0; _x1 = x1; _y1 = y1;
      isbase = is_base;
    }
    
    //Creating a super list with the given base rectangle as the first entry
    public Rect(Rect r)
    {
      _x0 = r._x0; _y0 = r._y0; _x1 = r._x1; _y1 = r._y1;
      isbase = false;
      subrecs = new List<Rect>();
      subrecs.Add(r);  //we bypass Rect.Add because we don't need to adjust size
    }
    
    //This will never be called on a base rect and is used to add new
    // subrecs
    public void AdjustSize(int x0, int y0, int x1, int y1)
    {
      if (x0 < _x0) _x0 = x0;
      if (y0 < _y0) _y0 = y0;
      if (x1 > _x1) _x1 = x1;
      if (y1 > _y1) _y1 = y1;
    }
    
    public void Add(Rect r)
    {
      AdjustSize(r._x0,r._y0,r._x1,r._y1);
      subrecs.Add(r);
    }
    
    public bool Intersects(Rect r)
    {
      return r._x0 < _x1 &amp;&amp; r._y0 < _y1 &amp;&amp; r._x1 > _x0 &amp;&amp; r._y1 > _y0; 
    }
    
    public bool Contains(Rect r)
    {
      return r._x0 >= _x0 &amp;&amp; r._y0 >= _y0 &amp;&amp; r._x1 <= _x1 &amp;&amp; r._y1 <= _y1;
    }
    
    public bool ContainedIn(Rect r)
    {
      return r.Contains(this);
    }

    public long Size()
    {
      //We only ever get size after smashing and we don't need pieces anymore
      long size = 0;
      if (subrecs == null)
        size = (long)(_x1-_x0) * (long)(_y1-_y0);
      else
      {
        foreach (Rect r in subrecs)
          size += r.Size();
        subrecs.Clear();
        subrecs = null;
      }
      return size;
    }

    //Pass in a list of rectangles (or super) that need to be compared
    // to the current rectangle.  Break up the current rectangle into sub-
    // rectangles to determine the area that has not yet been "covered".
    public void SmashThis(Rect smashee)
    {
      //We only call SmashMe with a base rectangle, otherwise we recurse
      
      if (isbase)
        smashee.SmashMe(this);
      else
        foreach (Rect r in subrecs)
          if (r.Intersects(smashee))
            r.SmashThis(smashee);
    }


    //Returns a list of smaller rectangles created by removing overlapping
    // area for a different rectangle.  Original rectangle should not be
    // modified.
    public List<Rect> GetSmashList(Rect tosmash)
    {
      int newx0 = _x0;
      int newx1 = _x1;
      List<Rect> smashlist;
      
      smashlist = new List<Rect>();
      //get piece on the left
      if (tosmash._x0 > _x0)
      {
        smashlist.Add(new Rect(_x0,_y0,tosmash._x0,_y1));
        newx0 = tosmash._x0;
      }
      //get piece on the right
      if (tosmash._x1 < _x1)
      {
        smashlist.Add(new Rect(tosmash._x1,_y0,_x1,_y1));
        newx1 = tosmash._x1;
      }
      //get bottom piece
      if (tosmash._y0 > _y0)
        smashlist.Add(new Rect(newx0,_y0,newx1,tosmash._y0));
      //get top piece
      if (tosmash._y1 < _y1)
        smashlist.Add(new Rect(newx0,tosmash._y1,newx1,_y1));
        
      return smashlist;
    }
    
    //We have a rectangle that overlaps this one and we want to break this one
    //up, removing any overlapping area
    //Note: parameter should probably be "smasher" to distinguish from "smashee"
    //  but I don't feel like changing all references.
    public void SmashMe(Rect tosmash)
    {
      List<Rect> tocheck;
      
      if (subrecs == null)
      {
        subrecs = GetSmashList(tosmash);
        return;
      }
      
      //We have already broken into subrecs
      tocheck = new List<Rect>();
      //we need to create a copy list since we will be removing things from the original list as we go
      foreach (Rect r in subrecs)
        tocheck.Add(r);
      //Now we process each of the sub rectangles
      foreach (Rect r in tocheck)
      {
        if (tosmash.Intersects(r))
        {
          subrecs.Remove(r);
          if (!tosmash.Contains(r))
          {
            //need to get left overs
            List<Rect> pieces = r.GetSmashList(tosmash);
            foreach (Rect piece in pieces)
              subrecs.Add(piece);
          }
        }
      }
    }
    
    
    //The following are display routines that made things a bit easier to debug.
    public override string ToString()
    {
      return string.Format("({0},{1}) to ({2},{3})", new object[] {_x0,_y0,_x1,_y1});
    }
    
    public void Display(bool withpieces = false)
    {
      if (isbase)
      {
        Console.WriteLine(string.Format("Base ({0},{1}) to ({2},{3})", new object[] {_x0,_y0,_x1,_y1}));
        if (withpieces &amp;&amp; (subrecs != null))
        {
          foreach (Rect r in subrecs)
            r.Display();
          Console.WriteLine(string.Format("Base Done ({0},{1}) to ({2},{3})", new object[] {_x0,_y0,_x1,_y1}));
        }
      }
      else
      {
        Console.WriteLine(string.Format("-Sub ({0},{1}) to ({2},{3})", new object[] {_x0,_y0,_x1,_y1}));
        if (subrecs != null)
        {
        foreach (Rect r in subrecs)
          r.Display();
        Console.WriteLine(string.Format("-Done ({0},{1}) to ({2},{3})", new object[] {_x0,_y0,_x1,_y1}));
        }
      }
    }
  }
}

答案10:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Solution
{
  public static class Kata
  {
    //list is sorted
    public static List<int[]> activeList = new List<int[]>(100);
    public static List<int[]> events = new List<int[]>(100);
      
    public static long RecalculateTopBottom()
    {
       
        int activeCount = activeList.Count();
        long size = 0;
        long current = 0;
        for(int i = 0; i < activeCount; i++)
        {
          //get are current bottom
          current = current > activeList[i][1] ? current : activeList[i][1];
          //should we add to our size?
          size +=  (activeList[i][3]-current) > 0 ? (activeList[i][3]-current) : 0;
          //see if top should be our current bottom
          current = current > activeList[i][3] ? current : activeList[i][3];
        }
        
       // Console.WriteLine("size {0}",size);
        return size;
    }
    
    
    public static long SweepMethod(IEnumerable<int[]> rectangles)
    {
       int iCount = rectangles.Count();
      if(iCount==0)
        return 0;
      
      long total = 0;
      List<int[]> rects = rectangles.OrderBy(x => x[0]).ToList();
      events.Clear();
      
      for(int h = 0; h < iCount; h++)
      {
        events.Add(new int[]{0, rects[h][0], h});
        events.Add(new int[]{1, rects[h][2], h});
      }
      
      events = events.OrderBy(x => x[1]).ToList(); //events order when sweping from left
      
      long iSize = 0;
      
      activeList.Clear();
      int eventCount = events.Count()-1; //minus one because we don't need to do last event
      long lastX = rects[0][0];
      Console.WriteLine(eventCount);
      
      for(int i = 0; i < eventCount &amp;&amp; i < 1000; i++)
      {
        //enters rect event
        if(events[i][0] == 0)
        {
          //events 2 is its index in the rects array
         // Console.WriteLine("add {0} {1}", i, events[i][2]);
          activeList.Add(rects[events[i][2]]);
          activeList = activeList.OrderBy(x => x[1]).ToList();
          iSize = RecalculateTopBottom();
        }
        else //remove rect event
        {
         // Console.WriteLine("remove {0} {1}", i, events[i][2]);
          bool bAnyChange = false;
          for(int j = 0; j < activeList.Count(); j++)
          {
             //events 2 is its index in the rects array
             if(rects[events[i][2]] == activeList[j])
             {
               //Console.WriteLine("remove event {0}",exitList[j][2]);
               activeList.RemoveAt(j);
               j--;
               bAnyChange = true;
             }
          }
          
          if(bAnyChange)
             iSize = RecalculateTopBottom();
        }
          
         total += (iSize*(events[i+1][1] - lastX));
         //Console.WriteLine("total {0} {1} {2}",total, events[i+1][1], lastX);
         lastX = events[i+1][1];
         //Console.WriteLine();
      }
      

      return total;
    }
    
    public static long RemoveOverlapMethod(IEnumerable<int[]> rectangles)
    {
      long total = 0;
      int Count = rectangles.Count();
      
      List<int[]> rects = rectangles.ToList();
      List<long[]> removed = new List<long[]>(100);
      
      long[] overlap = new long[4];
      long[] overlapExtra = new long[4];
      
      Console.WriteLine("count {0}", rectangles.Count());
      for(int j = 0; (j < Count); j++)
      {
        total += (long)(rects[j][2]-rects[j][0])*(long)(rects[j][3]-rects[j][1]);
       // Console.WriteLine("rec1 {0} {1} {2} {3}", rects[j][0],rects[j][1],rects[j][2],rects[j][3]);
       // Console.WriteLine("give areas   {0}", (long)(rects[j][2]-rects[j][0])*(long)(rects[j][3]-rects[j][1]));
        //Console.WriteLine("current      {0}", total);
        
        removed.Clear();
        for(int i = (j+1); (i < Count); i++)
        {
           if(rects[j][2] <= rects[i][0] || rects[j][0] >= rects[i][2] 
             || rects[j][1] >= rects[i][3] || rects[j][3] <= rects[i][1])
             continue;
             
           overlap[0] = (rects[j][0] > rects[i][0]) ? rects[j][0] : rects[i][0];
           overlap[1] = (rects[j][1] > rects[i][1]) ? rects[j][1] : rects[i][1];
           overlap[2] = (rects[j][2] < rects[i][2]) ? rects[j][2] : rects[i][2];
           overlap[3] = (rects[j][3] < rects[i][3]) ? rects[j][3] : rects[i][3];
           
           long extraOverlap = 0;
           //*
           for(int k = 0; k < removed.Count(); k++)
           {
           
             //Console.WriteLine("O {0} {1} {2} {3}", overlap[0], overlap[1],overlap[2],overlap[3]);
             //Console.WriteLine("R {0} {1} {2} {3}", removed[k][0], removed[k][1],removed[k][2],removed[k][3]);
           
           
             if(overlap[2] > removed[k][0] &amp;&amp; overlap[0] < removed[k][2] 
               &amp;&amp; overlap[1] < removed[k][3] &amp;&amp; overlap[3]> removed[k][1])
               {
                 overlapExtra[0] = (overlap[0] > removed[k][0]) ? overlap[0] : removed[k][0];
                 overlapExtra[1] = (overlap[1] > removed[k][1]) ? overlap[1] : removed[k][1];
                 overlapExtra[2] = (overlap[2] < removed[k][2]) ? overlap[2] : removed[k][2];
                 overlapExtra[3] = (overlap[3] < removed[k][3]) ? overlap[3] : removed[k][3];
                 extraOverlap += (overlapExtra[2]-overlapExtra[0])*(overlapExtra[3]-overlapExtra[1]);
                 //Console.WriteLine("G {0} {1} {2} {3}", overlapExtra[0], overlapExtra[1],overlapExtra[2],overlapExtra[3]);
                 //Console.WriteLine("extraOverlap {0}", (overlapExtra[2]-overlapExtra[0])*(overlapExtra[3]-overlapExtra[1]));
                
                }
           }//*/
             
           long removeArea = (overlap[2]-overlap[0])*(overlap[3]-overlap[1]);
           if(extraOverlap > removeArea)
             extraOverlap = removeArea;
           
           total -=  removeArea - extraOverlap;
           //Console.WriteLine("add O {0} {1} {2} {3}", overlap[0], overlap[1],overlap[2],overlap[3]);
           long[] saveOverlap = new long[4];
           saveOverlap[0] = overlap[0];
           saveOverlap[1] = overlap[1];
           saveOverlap[2] = overlap[2];
           saveOverlap[3] = overlap[3];
           removed.Add(saveOverlap);
           
         // Console.WriteLine("remove -{0} +{1}", removeArea, extraOverlap);
        }
        //Console.WriteLine("after remove {0}", total);
      // Console.WriteLine();
      }
     
      Console.WriteLine("ret {0}", total);
      return total;
    }
  
    public static long Calculate(IEnumerable<int[]> rectangles)
    {
      int iCount = rectangles.Count();
      if(iCount==0)
        return 0;
      
      if(iCount <= 1000)
        return SweepMethod(rectangles);
        
       return RemoveOverlapMethod(rectangles);
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值