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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值