算法题:水杯倒水的问题

简介:

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

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());
            }
        }
    }


相关文章
|
1月前
|
算法
【MATLAB】语音信号识别与处理:滑动平均滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:滑动平均滤波算法去噪及谱相减算法呈现频谱
45 0
|
30天前
|
传感器 算法 计算机视觉
基于肤色模型和中值滤波的手部检测算法FPGA实现,包括tb测试文件和MATLAB辅助验证
该内容是关于一个基于肤色模型和中值滤波的手部检测算法的描述,包括算法的运行效果图和所使用的软件版本(matlab2022a, vivado2019.2)。算法分为肤色分割和中值滤波两步,其中肤色模型在YCbCr色彩空间定义,中值滤波用于去除噪声。提供了一段核心程序代码,用于处理图像数据并在FPGA上实现。最终,检测结果输出到&quot;hand.txt&quot;文件。
|
1月前
|
机器学习/深度学习 算法 计算机视觉
基于yolov2深度学习网络的视频手部检测算法matlab仿真
基于yolov2深度学习网络的视频手部检测算法matlab仿真
|
1月前
|
算法
【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
23 2
|
1月前
|
算法
【MATLAB】语音信号识别与处理:卷积滑动平均滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:卷积滑动平均滤波算法去噪及谱相减算法呈现频谱
33 0
|
1月前
|
算法
【MATLAB】语音信号识别与处理:一维信号NLM非局部均值滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:一维信号NLM非局部均值滤波算法去噪及谱相减算法呈现频谱
39 1
|
3天前
|
机器学习/深度学习 人工智能 算法
基于DCT和扩频的音频水印嵌入提取算法matlab仿真
本文介绍了结合DCT和扩频技术的音频水印算法,用于在不降低音质的情况下嵌入版权信息。在matlab2022a中实现,算法利用DCT进行频域处理,通过扩频增强水印的隐蔽性和抗攻击性。核心程序展示了水印的嵌入与提取过程,包括DCT变换、水印扩频及反变换步骤。该方法有效且专业,未来研究将侧重于提高实用性和安全性。
|
7天前
|
文字识别 算法 计算机视觉
图像倾斜校正算法的MATLAB实现:图像倾斜角检测及校正
图像倾斜校正算法的MATLAB实现:图像倾斜角检测及校正
15 0
|
10天前
|
机器学习/深度学习 算法
【MATLAB】GA_ELM神经网络时序预测算法
【MATLAB】GA_ELM神经网络时序预测算法
282 9

热门文章

最新文章