算法题:水杯倒水的问题

2年前 (2022) 程序员胖胖胖虎阿
334 0 0

之前好像在博客园看到这样的题目:

1.有3个容器,各是20升,13升,7升, 形状不同也不透明。一开始20升的容器里面装了20升水,反正倒来倒去最后要让20升和13升容器各装了10升水

2. 2个外形不同的瓶子,各装800毫升水,另外还有1个300毫升的杯子

现在有4个人,不限制喝的次数,想办法让每个人都正好喝到400毫升水

第一第二道题目,口头说明解法就行了
第三个题,就是从第一第二题里面随便选择一个,使用编程来求解

于是乎..觉得有趣.便做了起来...花了一个下午的时间..终于做出来了:

首先建了一个水杯类: //以下程序只是基于可运行..至于代码的可看性和性能,暂时还没做优化
   public class Cut
    {
        private int _maxValue;//杯子的最大值
        public int MaxValue
        {
            get
            {
                return _maxValue;
            }
        }
        private int _currentValue;//杯子当前值
        public int CurrentValue
        {
            get
            {
                return _currentValue;
            }
            set
            {
                _currentValue = value;
            }
        }

        public Cut(int maxValue,int currentValue)
        {
            _maxValue = maxValue;
            _currentValue = currentValue;
        }
    }
然后在控制台程序环境下:
 class Program
    {
        private static List<int[]> valueList = new List<int[]>();//用于记录正确的步骤
        private static int[] values = new int[3];//当前的步骤
        private static Cut c7 = new Cut(7, 0);
        private static Cut c13 = new Cut(13, 0);
        private static Cut c20 = new Cut(20, 20);
        static void Main(string[] args)
        {
            valueList.Clear();
            ChangeCut(ref c7, ref c13, ref c20);
        }
        static bool GetDirection(int[] currentValues)//true表示可以继续下一次[节点不存在],false则反之[表示节点存在]
        {
            if (valueList.Count == 0)//第一次时.不存在重复节点,返回真
            {
                return true;
            }
            int count = 0;
            for (int i = 0; i < valueList.Count; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (valueList[i][j] == currentValues[j])//只要发现不相等,转入下一个
                    {
                        count++;
                        if (count == 3)
                        {
                            return false;
                        }
                    }
                    else
                    {
                        count = 0;
                        break;

                    }
                }
            }
            return true;

        }
        static void ChangeCut(ref Cut c1, ref Cut c2, ref Cut c3)
        {
            Cut cutA = c2;//第一次交换的值
            Cut cutB = c3;;//第一次交换的值
            while (true)
            {
                if (!ChangeTwoCut(ref cutA, ref cutB))//交换两个杯的值
                {
                    valueList.RemoveAt(valueList.Count - 1);//交换失败时.删除最后一个节点
                    c7.CurrentValue = valueList[valueList.Count - 1][0];//退回上一节点的值
                    c13.CurrentValue = valueList[valueList.Count - 1][1];//退回上一节点的值
                    c20.CurrentValue = valueList[valueList.Count - 1][2];//退回上一节点的值

                }
                RadomCut(ref c1, ref c2, ref c3, out cutA, out cutB);//随机取两个杯交换
            }
        }
        static void RadomCut(ref Cut c1, ref Cut c2, ref Cut c3, out  Cut c11, out Cut c12)//随机产生两个杯
        {
            Random rd = new Random();
            int result = rd.Next(3);
            if (result == 0)
            {
                c11 = c1;
            }
            else if (result == 1)
            {
                c11 = c2;
            }
            else
            {
                c11 = c3;
            }
            int result2 = rd.Next(3);
            while (result2 == result)//用于产生不和上面重复的值
            {
                result2 = rd.Next(2);
            }
            if (result2 == 0)
            {
                c12 = c1;
            }
            else if (result2 == 1)
            {
                c12 = c2;
            }
            else
            {
                c12 = c3;
            }
        }
        static bool ChangeTwoCut(ref Cut c1, ref Cut c2)
        {
            bool result = false;
            int valueA;
            int valueB;
            int tempA = c1.CurrentValue;
            int tempB = c2.CurrentValue;
          //默认先走左边
            GetChangedValue(c1, c2, out valueA, out valueB, true);//两个杯交换后的值
            c1.CurrentValue = valueA;
            c2.CurrentValue = valueB;
            if (GetDirection(new int[] { c7.CurrentValue, c13.CurrentValue, c20.CurrentValue }))
            {
                result = true;
            }
            else  //走右边
            {
                GetChangedValue(c1, c2, out valueA, out valueB, false);
                c1.CurrentValue = valueA;
                c2.CurrentValue = valueB;
                if (GetDirection(new int[] { c7.CurrentValue, c13.CurrentValue, c20.CurrentValue }))
                {
                    result = true;
                }
            }
            if (result)
            {
                GetResult();
            }
            else //失败,还原值
            {
                c1.CurrentValue = tempA;
                c2.CurrentValue = tempB;
            }
            return result;
        }
        static void GetChangedValue(Cut c1, Cut c2, out int valueA, out int valueB, bool AtoB)//两种情况,一种A的值给B,一种B的值给A
        {
            int maxValue = c1.CurrentValue + c2.CurrentValue;
            //边界测定
            if (c1.CurrentValue == 0)
            {
                valueA = c2.CurrentValue > c1.MaxValue ? c1.MaxValue : maxValue;
                valueB = maxValue - valueA;
            }
            else if (c1.CurrentValue == c1.MaxValue)
            {
                int need = c2.MaxValue - c2.CurrentValue;
                if (c1.CurrentValue >= need)
                {
                    valueA = c1.CurrentValue - need;
                    valueB = c2.CurrentValue + need;
                }
                else
                {
                    valueA = 0;
                    valueB = maxValue;
                }
            }
            else if (c2.CurrentValue == 0)
            {
                valueB = c1.CurrentValue > c2.MaxValue ? c2.MaxValue : maxValue;
                valueA = maxValue - valueB;
            }
            else if (c2.CurrentValue == c2.MaxValue)
            {
                int need = c1.MaxValue - c1.CurrentValue;
                if (c2.CurrentValue > need)
                {
                    valueA = c1.CurrentValue + need;
                    valueB = c2.CurrentValue - need;
                }
                else
                {
                    valueA = maxValue;
                    valueB = 0;
                }
            }
            else //非边界值时
            {
                if (AtoB)//A的值给B时
                {
                    valueB = maxValue > c2.MaxValue ? c2.MaxValue : maxValue;
                    valueA = maxValue - valueB;
                }
                else//B的值给A时
                {
                    valueA = maxValue > c1.MaxValue ? c1.MaxValue : maxValue;
                    valueB = maxValue - valueA;
                }
            }
        }

        static void GetResult() //添加正确步骤或显示结果
        {
            if (c20.CurrentValue == 10 || c13.CurrentValue == 10)
            {
                int[] newValue = new int[3] { c7.CurrentValue, c13.CurrentValue, c20.CurrentValue };
                valueList.Add(newValue);
                Console.WriteLine("结果已出如下:");
                for (int i = 0; i < valueList.Count; i++)
                {
                    Console.WriteLine("第" + i.ToString() + "步: " + valueList[i][0].ToString() + ":" + valueList[i][1].ToString() + ":" + valueList[i][2].ToString());
                }
                Console.ReadLine();
            }
            else
            {
                int[] newValue = new int[3] { c7.CurrentValue, c13.CurrentValue, c20.CurrentValue };
                valueList.Add(newValue);
                Console.WriteLine(newValue[0].ToString() + ":" + newValue[1].ToString() + ":" + newValue[2].ToString());
            }
        }
    }

版权声明:程序员胖胖胖虎阿 发表于 2022年10月11日 上午2:40。
转载请注明:算法题:水杯倒水的问题 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...