C# -算法:三桶等分水问题

7 篇文章 0 订阅
namespace 三桶等分水问题
{
    class Program
    {
        /// <summary>
        /// 初始桶存水信息
        /// </summary>
        static int[] start = new int[] { 8, 0, 0 };
        /// <summary>
        /// 所有桶最大水容量信息
        /// </summary>
        static int[] MaxVolume = new int[] { 8, 5, 3 };
        /// <summary>
        /// 结束桶存水信息
        /// </summary>
        static int[] end = new int[] { 4, 4, 0 };
        /// <summary>
        /// 桶数量
        /// </summary>
        static int len;
        /// <summary>
        /// 方法数
        /// </summary>
        static int number = 0;
        static void Main(string[] args)
        {
            len = start.Length;
            List<Course> result = new List<Course>();
            result.Add(new Course(start));
            GetDumpCourse(result);
            Console.ReadLine();
        }
        /// <summary>
        /// 根据所有桶的现存水的数组信息初始化桶数组信息
        /// </summary>
        /// <param name="NowVolume">所有桶的现存水的数组信息</param>
        /// <returns></returns>
        private static Bucket[] InitBucketList(int[] NowVolume)
        {
            var list = new Bucket[len];
            for (int i = 0; i < len; i++)
            {
                list[i] = new Bucket(NowVolume[i], MaxVolume[i]);
            }
            return list;
        }
        /// <summary>
        /// 获取倒水数组信息
        /// </summary>
        /// <param name="result">上一步的倒水数组信息</param>
        private static void GetDumpCourse(List<Course> result)
        {
            int cut = result.Count;
            var num = result[cut - 1].bucketExisting;//倒水数组的最后的桶存水数组信息
            var list = InitBucketList(num);
            int cnt = len * len;
            for (int i = 0; i < cnt; i++)
            {
                int r = i / len;//将二重循环降为一重循环,r为横坐标
                int c = i % len;//将二重循环降为一重循环,c为纵坐标
                if (Enumerable.SequenceEqual(num, end))//判断是否已经符合结束桶存水信息
                {
                    WriteDumpCourse(result);
                    return;
                }
                if (CheckBucket(r, c, list))
                {
                    //尝试倒水
                    int maxGive = list[r].existing;
                    int maxGain = list[c].volume - list[c].existing;
                    int min = maxGive;
                    if (min >= maxGain)
                    {
                        min = maxGain;
                    }
                    list[c].existing += min;
                    list[r].existing -= min;
                    //倒水过程加入数组
                    result.Add(new Course(min, r + 1, c + 1));
                    if (CheckDump(result, list))
                        GetDumpCourse(result);
                    //恢复原状态
                    list[c].existing -= min;
                    list[r].existing += min;
                    result.RemoveAt(cut);
                }
            }
        }
        /// <summary>
        /// 输出倒水过程信息
        /// </summary>
        /// <param name="courseList">倒水过程数组</param>
        private static void WriteDumpCourse(List<Course> courseList)
        {
            Console.WriteLine("第{0}种方法:一共有{1}步步骤:\n", ++number, courseList.Count);
            foreach (Course c in courseList)
            {
                Console.WriteLine("从 {0} 桶倒 {1} 水入 {2} 桶,所有桶的水量是:{3}", c.fromNumber, c.dumpVolume, c.toNumber, string.Join(" ", c.bucketExisting));
            }
            Console.WriteLine();
        }
        /// <summary>
        /// 判断倒水过程(若原过程数组中有与此次倒水之后的桶数组信息相同的,则判断倒水过程数组中有循环操作,舍弃,没有则判断倒水过程符合,加入倒水过程数组)
        /// </summary>
        /// <param name="courseList">过程数组</param>
        /// <param name="list">此次倒水之后的桶数组信息</param>
        /// <returns></returns>
        private static bool CheckDump(List<Course> courseList, Bucket[] list)
        {
            int[] num = new int[len];
            for (int j = 0; j < len; j++)
            {
                num[j] = list[j].existing;
            }
            int cnt = courseList.Count;
            for (int i = 0; i < cnt - 1; i++)
            {
                if (Enumerable.SequenceEqual(courseList[i].bucketExisting, num))
                    return false;
            }
            courseList[cnt - 1].bucketExisting = num;
            return true;
        }
        /// <summary>
        /// 判断是否可以倒水
        /// </summary>
        /// <param name="r">水来源桶</param>
        /// <param name="c">水倒入桶</param>
        /// <param name="list">桶数组</param>
        /// <returns></returns>
        private static bool CheckBucket(int r, int c, Bucket[] list)
        {
            if (r == c) return false; //水来源桶与水倒入桶为同一个桶,不能倒水
            if (list[r].existing == 0) return false;//水来源桶没水,不能倒水
            if (list[c].existing == list[c].volume) return false;//水倒入桶已满,不能倒水
            return true;
        }
        /// <summary>
        /// 类-桶
        /// </summary>
        class Bucket
        {
            /// <summary>
            /// 最大容量
            /// </summary>
            public int volume;
            /// <summary>
            /// 现存水量
            /// </summary>
            public int existing;
            public Bucket(int exist, int maxV)
            {
                volume = maxV;
                existing = exist;
            }
        }
        /// <summary>
        /// 类-倒水过程
        /// </summary>
        class Course
        {
            /// <summary>
            /// 倒水量
            /// </summary>
            public int dumpVolume;
            /// <summary>
            /// 水来源桶号
            /// </summary>
            public int fromNumber;
            /// <summary>
            /// 水倒入桶号
            /// </summary>
            public int toNumber;
            /// <summary>
            /// 所有桶现存水数组信息
            /// </summary>
            public int[] bucketExisting;

            public Course(int dumpV, int from, int to)
            {
                // TODO: Complete member initialization
                this.dumpVolume = dumpV;
                this.fromNumber = from;
                this.toNumber = to;
            }

            public Course(int[] start)
            {
                dumpVolume = start[0];
                fromNumber = 0;
                toNumber = 1;
                bucketExisting = new int[len];
                for (int i = 0; i < len; i++)
                {
                    bucketExisting[i] = start[i];
                }
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值