예제 #1
0
    public unsafe string AnnealOnConstCurve()
    {
        const int len      = Const.N + 2;
        int *     distance = stackalloc int[len << 7];
        var       curve    = Util.HilvertCurve.ToArray();

        for (int i = 1; i <= Const.N; i++)
        {
            var(iby, ibx) = Board[i];
            var(icy, icx) = curve[i - 1];
            for (int j = 1; j <= Const.N; j++)
            {
                var(jby, jbx) = Board[j];
                var(jcy, jcx) = curve[j - 1];
                var dist = Abs(iby - jby) + Abs(ibx - jbx) + Abs(icy - jcy) + Abs(icx - jcx);
                distance[(i << 7) + j] = dist;
            }
        }
        for (int i = 1; i <= Const.N; i++)
        {
            // Init cost
            var(iby, ibx) = Board[i];
            var(icy, icx) = curve[i - 1];
            int minBY = Min(iby, 19 - iby);
            int minBX = Min(ibx, 19 - ibx);
            int minCY = Min(icy, 9 - icy);
            int minCX = Min(icx, 9 - icx);



            var cost = Min(Max(minCY - minBY, 0) + Max(minCX - minBX, 0), Max(minCY - minBX, 0) + Max(minCX - minBY, 0));
            //if (0 < cost) cost += 8;

            //原点からの距離/一番最後にカーブに置くものから0への距離が必要
            distance[(0 << 7) + i]         = iby + ibx + icy + icx;
            distance[(i << 7) + (len - 1)] = 0;
        }

        //0がスタート、n+2がゴール
        int        ind = 1;
        Span <int> cur = stackalloc int[len];

        bool[] used = new bool[len];
        for (int i = 0; i < Const.H; i += 4)
        {
            int begin, end, d;
            if ((i / 4) % 2 == 0)
            {
                (begin, end, d) = (0, Const.W, 1);
            }
            else
            {
                (begin, end, d) = (Const.W - 1, -1, -1);
            }
            for (int j = begin; j != end; j += d)
            {
                int nbegin, nend, nd;
                if (j % 2 != 0)
                {
                    (nbegin, nend, nd) = (i, i + 4, 1);
                }
                else
                {
                    (nbegin, nend, nd) = (i + 3, i - 1, -1);
                }
                for (int k = nbegin; k != nend; k += nd)
                {
                    if (Board[k, j] != 0)
                    {
                        cur[ind++] = Board[k, j];
                    }
                }
            }
        }
        cur[ind] = len - 1;

        int curCost = 0;

        for (int i = 0; i < len - 1; i++)
        {
            curCost += distance[(cur[i] << 7) + cur[i + 1]];
        }
        curCost += 100 - 1;

        Span <int> minRes = stackalloc int[len];

        cur.CopyTo(minRes);
        int minCost = curCost;

        #region Anneal
#if TRUE
        const double startTemp = 16.4;
        const double endTemp   = 0.15;

        int    cnt  = 0;
        double temp = 0;

        var muler = (1 / 0.975) / Const.TL;

        while (true)
        {
            if ((cnt & 1024) == 0)
            {
                var progress = (double)(DateTime.Now - StartAt).TotalSeconds * muler;
                temp = startTemp + (endTemp - startTemp) * progress;
                if (1 <= progress)
                {
                    break;
                }
            }
            cnt++;

            int a = RNG.Next() % Const.N, b;
            do
            {
                b = RNG.Next() % Const.N;
            } while (b == a);
            // a < b
            if (a > b)
            {
                (a, b) = (b, a);
            }
            a++; b++;

            var curdist = distance[(cur[a - 1] << 7) + cur[a]] + distance[(cur[b] << 7) + cur[b + 1]];
            var nxtdist = distance[(cur[a - 1] << 7) + cur[b]] + distance[(cur[a] << 7) + cur[b + 1]];
            //curdistの方が大きいと嬉しいよ 大きいと正になるのはcurdist - nxtdist
            var prob = Exp((curdist - nxtdist) / temp);

            if (prob * uint.MaxValue > RNG.UInt)
            {
                MemoryExtensions.Reverse(cur.Slice(a, b - a + 1));
                curCost = curCost - curdist + nxtdist;
                if (curCost < minCost)
                {
                    cur.CopyTo(minRes);
                    minCost = curCost;
                }
            }
        }
예제 #2
0
    public unsafe string AnnealOnConstCurve()
    {
        const int len      = Const.N + 2;
        int *     distance = stackalloc int[len << 7];
        var       curve    = Util.HilvertCurve.ToArray();

        for (int i = 1; i <= Const.N; i++)
        {
            var(iby, ibx) = Board[i];
            var(icy, icx) = curve[i - 1];
            for (int j = 1; j <= Const.N; j++)
            {
                var(jby, jbx) = Board[j];
                var(jcy, jcx) = curve[j - 1];
                var dist = Abs(iby - jby) + Abs(ibx - jbx) + Abs(icy - jcy) + Abs(icx - jcx);
                distance[(i << 7) + j] = dist;
            }
        }
        for (int i = 1; i <= Const.N; i++)
        {
            var(iby, ibx) = Board[i];
            var(icy, icx) = curve[i - 1];
            var(zcy, zcx) = curve[0];
            var maxdist = new[] { icy, 9 - icy, icx, 9 - icx }.Max();
            //原点からの距離/一番最初に取るものから0への距離が必要
            distance[(0 << 7) + i]         = iby + ibx + Abs(zcy - icy) + Abs(zcx - icx);
            distance[(i << 7) + (len - 1)] = Max(0, 5 - maxdist);
        }

        //0がスタート、n+2がゴール
        Span <int> cur = stackalloc int[len];

        for (int i = 0; i < len; i++)
        {
            cur[i] = i;
        }

        int curCost = 0;

        for (int i = 0; i < len - 1; i++)
        {
            curCost += distance[(cur[i] << 7) + cur[i + 1]];
        }
        curCost += 100 - 1;

        Span <int> minRes = stackalloc int[len];

        cur.CopyTo(minRes);
        int minCost = curCost;

        #region Anneal
#if TRUE
        const double startTemp = 16.4;
        const double endTemp   = 0.15;

        int    cnt  = 0;
        double temp = 0;

        var muler = (1 / 0.975) / Const.TL;

        while (true)
        {
            if ((cnt & 1024) == 0)
            {
                var progress = (double)(DateTime.Now - StartAt).TotalSeconds * muler;
                temp = startTemp + (endTemp - startTemp) * progress;
                if (1 <= progress)
                {
                    break;
                }
            }
            cnt++;

            int a = RNG.Next() % Const.N, b;
            do
            {
                b = RNG.Next() % Const.N;
            } while (b == a);
            // a < b
            if (a > b)
            {
                (a, b) = (b, a);
            }
            a++; b++;

            var curdist = distance[(cur[a - 1] << 7) + cur[a]] + distance[(cur[b] << 7) + cur[b + 1]];
            var nxtdist = distance[(cur[a - 1] << 7) + cur[b]] + distance[(cur[a] << 7) + cur[b + 1]];
            //curdistの方が大きいと嬉しいよ 大きいと正になるのはcurdist - nxtdist
            var prob = Exp((curdist - nxtdist) / temp);

            if (prob * uint.MaxValue > RNG.UInt)
            {
                MemoryExtensions.Reverse(cur.Slice(a, b - a + 1));
                curCost = curCost - curdist + nxtdist;
                if (curCost < minCost)
                {
                    cur.CopyTo(minRes);
                    minCost = curCost;
                }
            }
        }