将一个数组中的元素利用另一个数组中的元素进行拆分

来源:互联网 发布:ip与mac绑定是什么意思 编辑:程序博客网 时间:2024/05/16 14:23
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace ConsoleApplication2{    public class Pair<IClass, JClass>    {        public IClass I { get; set; }        public JClass J { get; set; }    }    public class Pair<IClass, JClass, KClass>    {        public IClass I { get; set; }        public JClass J { get; set; }        public KClass K { get; set; }        public Pair(IClass i, JClass j, KClass k)        {            I = i;            J = j;            K = k;        }        public Pair(IClass i, JClass j)        {            I = i;            J = j;        }    }    public class Split    {        private const double Expected = 0.7;        public static List<Pair<double, double, decimal>> Resolve(List<double> m, List<double> n)        {            Console.WriteLine(".................................start to get resolution.................................");            // m: sum array            // n: item array            n = n.OrderByDescending(x => x).ToList();            var mapping = new Dictionary<Pair<int, double>, List<List<int>>>();            List<List<int>> temp;            int i = 0;            foreach (var mth in m)            {                temp = GetComb(mth, n);                if (temp.Count > 0) mapping[new Pair<int, double> { I = i, J = mth }] = temp;                else                {                    Console.WriteLine("data error");                    return null;                }                i++;            }            var result = GetOpt(mapping.Values.ToList());            if (IsTrueSolution(result)) Console.WriteLine("this is a real solution");            foreach (var item in result)            {                item.I = n[(int)item.I];                item.J = n[(int)item.J];                item.K = (decimal)item.I + (decimal)item.J;                Console.WriteLine(item.K);            }            return result;        }        static bool IsTrueSolution(List<Pair<double, double, decimal>> result)        {            var list = result.SelectMany(m => new int[] { (int)m.I, (int)m.J }).ToList();            return list.Distinct().Count() == list.Count;        }        /// <summary>        ///         /// </summary>        /// <param name="set"></param>        /// <returns>index in the 2nd-layered list</returns>        static List<Pair<double, double, decimal>> GetOpt(List<List<List<int>>> set)        {            set = set.OrderBy(m => m.Count).ToList();            var set1 = new List<int>();            int i = 0, len = set.Count;            int j = 0;            Stack<Pair<int, int>> stack = new Stack<Pair<int, int>>();            Pair<int, int> pair;            int max = 0;            List<Pair<int, int>> result = null;            ulong iter = 0;            double realTimeElapsed = 0;            var watcher = new System.Diagnostics.Stopwatch();            watcher.Start();            do            {                if (watcher.Elapsed.TotalSeconds > 540) break;                while (i < len)                {                    iter++;                    while (j < set[i].Count)                    {                        iter++;                        if (!IsCollided(set1, set[i][j]))                        {                            MergeToFirst(set1, set[i][j]);                            stack.Push(new Pair<int, int> { I = i, J = j });                            if (stack.Count > max)                            {                                max = stack.Count;                                if (max >= (int)len * Expected) result = stack.Select(m => new Pair<int, int> { I = m.I, J = m.J }).ToList();                                realTimeElapsed = watcher.Elapsed.TotalSeconds;                            }                            break;                        }                        j++;                    }                    i++;                    j = 0;                }                if (stack.Count != len)                {                    do                    {                        iter++;                        pair = stack.Pop();                        RemoveFromFirst(set1, set[pair.I][pair.J]);                        i = pair.I;                        j = pair.J + 1;                        while (j < set[i].Count)                        {                            iter++;                            if (!IsCollided(set1, set[i][j]))                            {                                MergeToFirst(set1, set[i][j]);                                stack.Push(new Pair<int, int> { I = i, J = j });                                if (stack.Count > max)                                {                                    max = stack.Count;                                    if (max >= (int)len * Expected) result = stack.Select(m => new Pair<int, int> { I = m.I, J = m.J }).ToList();                                    realTimeElapsed = watcher.Elapsed.TotalSeconds;                                }                                break;                            }                            j++;                        }                    } while (j >= set[i].Count && (stack.Count > 0));                    i++;                    j = 0;                    if ((stack.Count + len - i) < max)                    {                        i = len;                    }                    if (stack.Count == 0)                    {                        set1.Clear();                    }                }                else                {                    break;                }            } while (stack.Count > 0 || i < len);            Console.WriteLine("total iteration:{0} with real time elapsed: {1}", iter, realTimeElapsed);            var solution = new List<Pair<double, double, decimal>>();            if (result == null) result = stack.Select(m => new Pair<int, int> { I = m.I, J = m.J }).ToList();            foreach (var p in result)            {                solution.Add(new Pair<double, double, decimal>(set[p.I][p.J][0], set[p.I][p.J][1]));            }            return solution;        }        /// <summary>        ///         /// </summary>        /// <param name="set1"></param>        /// <param name="set2">has only 2 items</param>        /// <returns></returns>        static bool IsCollided(List<int> set1, List<int> set2)        {            if (set1.Count == 0 || set2.Count == 0) return false;            var result = false;            foreach (var v in set2)            {                if (result) break;                result = result || (BSearch(set1, v) != -1);            }            return result;        }        static int BSearch(List<int> set1, int v)        {            var pos = -1;            int i = 0, j = set1.Count - 1, mid;            while (i <= j)            {                mid = (i + j) / 2;                if (set1[mid] > v)                {                    if (i == mid) i = mid + 1;                    else i = mid;                }                else if (set1[mid] < v)                {                    if (j == mid) j = mid - 1;                    else j = mid;                }                else                {                    pos = mid;                    break;                }            }            return pos;        }        static void MergeToFirst(List<int> set1, List<int> set2)        {            foreach(var v in set2)            {                set1.Insert(GetInsertPos(set1, v), v);            }        }        static int GetInsertPos(List<int> set1, int v)        {            if (set1.Count == 0) return 0;            int i = 0, j = set1.Count - 1, mid;            while (i <= j)            {                mid = (i + j) / 2;                if (set1[mid] > v)                {                    if (mid + 1 >= set1.Count) return mid + 1;                    if (set1[mid + 1] < v) return mid + 1;                    if (i == mid) i = mid + 1;                    else i = mid;                }                else if (set1[mid] < v)                {                    if ((mid - 1 < 0) || set1[mid - 1] > v) return mid;                    if (j == mid) j = mid - 1;                    else j = mid;                }                else                {                    return mid;                }            }            return -1;        }        static void RemoveFromFirst(List<int> set1, List<int> set2)        {            foreach (var v in set2)            {                set1.RemoveAt(BSearch(set1, v));            }        }        static List<List<int>> GetComb(double value, List<double> items, double deviation = 0)        {            var result = new List<List<int>>();            int i = 0, j = items.Count - 1;            decimal sum;            while (i < j)            {                sum = (decimal)items[i] + (decimal)items[j] - (decimal)value;                if (sum > 0) i++;                else if (sum < 0) j--;                else                {                    result.Add(new List<int> { i, j });                    i++; j--;                }            }            return result;        }    }}

0 0