找空空间的公式

时间:2015-10-15 12:59:51

标签: c#

View Image for reference

大家好,

我需要有关逻辑的建议。我的情景是,

有一个空格Size is Height: 200, Width 200

  • 我填补了一些空间Height: 100, Width 100

  • 我再次填补空间Height : 50 Width : 50

我只想找到方向空的空间。例如

如果我试图占据Height = 100 and Width = 200,那就是正确的

如果我试图占据Height = 200 and width = 100应该说这是错误的。

查看图片以获得清晰的想法

如何处理这种情况..有什么想法吗?

谢谢大家的宝贵时间,我认为我的问题是没有足够的细节,好的,这里只增加了一些信息,例如,

我的木材尺寸为(200 x 200)(高x宽)

  • 首先要切割尺寸为100 x 100的木材 (这里我需要公式来检查这个木材中是否有这个值)
  • 现在该公式应该说,是的,它是可用的

  • 再次想要切割尺寸为50 x 50 (这里我需要公式来检查这个木材是否有这个值) - 现在的公式应该说,是的,它是可用的

  • 再次想要切割尺寸为100 x 200(高度:200,宽度:100) - 现在的公式应该说,没有这个空间不可用

  • 再想切割尺寸为200 x 100(高度:100,宽度:200)

    • 现在公式应该说,是的,它是可用的

注意:切割尺寸可能会改变 我希望你明白我想说的是什么

由于

3 个答案:

答案 0 :(得分:1)

你的问题不够明确,无法给你一个完整的答案。无论如何,在this帖子中,您可以找到将一系列矩形放入一个封闭矩形的全局问题的解决方案。

解决方案的关键在于DynamicTwoDimensionArray类:每次在可用空间中添加一个矩形时,都会将区域分成四个部分,其中三个部分仍为空。如果你记住所有空闲空间的高度和宽度,你只需要测试新的矩形是否适合它们。

答案 1 :(得分:1)

在OP编辑了它的问题之后,现在很清楚它的程序必须做什么。

我给出的另一个答案是指一个完整的程序,在一个人的设计中难以遵循并难以使用,所以我决定从头开始制作一切。

也许任何被分配了2d装箱问题的学生都会更容易理解和使用。

我们走了......

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

namespace WoodCutter {

    /// <summary>
    /// This class represents a continuous area of wood
    /// </summary>
    public class Freespace {
        private int x, y, height, width;
        /// <summary>
        /// Public constructor of the class
        /// </summary>
        /// <param name="x">Leftmost position of the area</param>
        /// <param name="y">Topmost position of the area</param>
        /// <param name="height">Vertical extent of the area</param>
        /// <param name="width">Horizontal extent of the area</param>
        public Freespace(int x, int y, int height, int width) {
            this.x = x;
            this.y = y;
            this.height = height;
            this.width = width;
        }
        /// <summary>
        /// Leftmost position of the area
        /// </summary>
        public int xLeft {
            get { return this.x; }
        }
        /// <summary>
        /// Topmost position of the area
        /// </summary>
        public int yUp {
            get { return this.y; }
        }
        /// <summary>
        /// Tests if this area can contain a cut of the given height and width
        /// </summary>
        /// <param name="height">Vertical extent of the needed cut</param>
        /// <param name="width">Horizontal extent of the needed cut</param>
        /// <returns>true if this Freespce can contain the needed cut else false</returns>
        public bool Contains(int height, int width) {
            if (this.width >= width && this.height >= height) {
                return true;
            }
            return false;
        }
        /// <summary>
        /// Creates cuts from this Freespace
        /// If the proposed cut does not intersect with this Freespace, do nothing and return a List containing this.
        /// If the proposed cut completely contains this Freespace, return an empty List.
        /// When the cut intersects the Freespace, cut the Freespace with the semiplanes around the desired cut
        /// </summary>
        /// <param name="x">Leftmost position of the cut</param>
        /// <param name="y">Topmost position of the cut</param>
        /// <param name="height">Vertical extent of the cut</param>
        /// <param name="width">Horizontal extent of the cut</param>
        /// <returns>List of Freespaces created from the intersection of the Freespace and the cut</returns>
        public List<Freespace> Cut(int x, int y, int height, int width) {
            List<Freespace> res = new List<Freespace>();
            if ((x - this.x) >= this.width || 
                (y - this.y) >= this.height || 
                (x + width) < this.x || 
                (y + height) < this.y) {
                // no intersection, return myself
                res.Add(this);
                return res;
            }
            if (x <= this.x && 
                y <= this.y && 
                (x + width) >= (this.x + this.width) && 
                (y + height) >= (this.y + this.height)) {
                // the cut covers the whole freespce, return empty list
                return res;
            }
            if (x > this.x) {
                // cut this freespace with the semiplane of abscissas less than x
                res.Add(new Freespace(this.x, this.y, this.height, x - this.x));
            }
            if (y > this.y) {
                // cut this freespace with the semiplane of ordinates less than y
                res.Add(new Freespace(this.x, this.y, y - this.y, this.width));
            }
            if ((x + width) < (this.x + this.width)) {
                // cut this freespace with the semiplane of abscissas greater than x+width
                res.Add(new Freespace(x + width, this.y, this.height, this.width - width));
            }
            if ((y + height) < (this.y + this.height)) {   
                // cut this freespace with the semiplane of ordinates greater than y+height
                res.Add(new Freespace(x, y + height, this.height - height, this.width));
            }
            return res;
        }
        public void Write2Console() {
            Console.WriteLine("Freespace at {0},{1} of dimensions {2},{3}", this.x, this.y, this.width, this.height);
        }
    }

    /// <summary>
    /// This class holds a List of Freespaces that can be cut
    /// At the beginning you have only one Freespace covering the whole plane, 
    /// adding cuts the List gets populated with all the residual areas.
    /// </summary>
    public class Wood {
        private List<Freespace> freeSpaces;
        /// <summary>
        /// Public constructor
        /// </summary>
        /// <param name="height">Vertical extent of the area</param>
        /// <param name="width">Horizontal extent of the area</param>
        public Wood(int height, int width) {
            this.freeSpaces = new List<Freespace>();
            this.freeSpaces.Add(new Freespace(0, 0, height, width));
        }
        /// <summary>
        /// Returns the first Freespace (or null) that can contain the whole cut
        /// </summary>
        /// <param name="height">Vertical extent of the cut</param>
        /// <param name="width">Horizontal extent of the cut</param>
        /// <returns>First Freespace completely containing the cut or null</returns>
        public Freespace canCut(int height, int width) {
            foreach (Freespace f in this.freeSpaces) {
                if (f.Contains(height, width)) {
                    return f;
                }
            }
            return null;
        }
        /// <summary>
        /// Makes the cut in the Wood.
        /// Intersects the desired cut with all the Freespaces in the List.
        /// WARNING. No check is made, at this point, if you can do the cut. 
        ///          You have to call the canCut function before using this method 
        ///          and take the adequate coordinates from the Freespace returned.
        /// </summary>
        /// <param name="x">Leftmost position of the cut</param>
        /// <param name="y">Topmost position of the cut</param>
        /// <param name="height">Vertical extent of the cut</param>
        /// <param name="width">Horizontal extent of the cut</param>
        public void Cut(int x, int y, int height, int width) {
            List<Freespace> freeSpaces = new List<Freespace>();
            foreach (Freespace f in this.freeSpaces) {
                freeSpaces.AddRange(f.Cut(x, y, height, width));
            }
            this.freeSpaces = freeSpaces;
        }
        public void Write2Console() {
            foreach (Freespace f in this.freeSpaces) {
                f.Write2Console();
            }
        }
    }

    class WoodCutter {
        /// <summary>
        /// Tests if a cut can be made in the wood and, if true
        /// cuts it at the upper leftmost coordinate of the first
        /// adequate Freespace found.
        /// </summary>
        /// <param name="wood">The wood to cut</param>
        /// <param name="width">The width of thr cut</param>
        /// <param name="heigth">The height of the cut</param>
        private static void testCut(Wood wood, int width, int heigth) {
            Freespace f;
            f = wood.canCut(heigth, width);
            if (f != null) {
                Console.WriteLine("Can cut a {0} by {1} piece", width, heigth);
                wood.Cut(f.xLeft, f.yUp, heigth, width);
            } else {
                Console.WriteLine("Cannot fit a {0} by {1} piece", width, heigth);
            }
        }
        static void Main(string[] args) {
            // Let's start with a 200X200 wood
            Wood wood = new Wood(200, 200);
            wood.Write2Console();

            //Try and cut a 100X100 piece
            testCut(wood, 100, 100);
            wood.Write2Console();

            //Try and cut a 50X50 piece
            testCut(wood, 50, 50);
            wood.Write2Console();

            //Try to cut a 100X200 piece (this should fail)
            testCut(wood, 100, 200);
            wood.Write2Console();

            //Try and cut a 200X100 piece
            testCut(wood, 200, 100);
            wood.Write2Console();

            Console.WriteLine("Program end.");
        }
    }
}

您可以做的最好的事情就是运行代码并逐步完成它以了解它是如何工作的。以下是预期的输出:

Freespace at 0,0 of dimensions 200,200
Can cut a 100 by 100 piece
Freespace at 100,0 of dimensions 100,200
Freespace at 0,100 of dimensions 200,100
Can cut a 50 by 50 piece
Freespace at 150,0 of dimensions 50,200
Freespace at 100,50 of dimensions 100,150
Freespace at 0,100 of dimensions 200,100
Cannot fit a 100 by 200 piece
Freespace at 150,0 of dimensions 50,200
Freespace at 100,50 of dimensions 100,150
Freespace at 0,100 of dimensions 200,100
Can cut a 200 by 100 piece
Freespace at 150,0 of dimensions 50,100
Freespace at 100,50 of dimensions 100,50

希望它有所帮助,对任何问题进行投票和评论:D。

答案 2 :(得分:0)

此解决方案的工作原理是假设填充的区域是恒定的。

private static bool NewValueFit(int xfoo, int ybar)
{
    if (xfoo > 200 || ybar > 200)
        return false;            
    if (ybar <= 100)
        return true;
    else if (ybar <= 150)
    {
        if (xfoo <= 100)
            return true;
    else
            return false;
    }
    else if (xfoo <= 50)
        return true;
    else
        return false;
}