Submission #65209566


Source Code Expand

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Text;

public class Solution
{
    public const int TIME_LIMIT = 1700;
    public static void Main()
    {
        int[] inputs = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
        Board.Size = inputs[0];
        Board.InitBoard();
        int m = inputs[1];
        List<Cell> path = new List<Cell>();
        for (int i = 0; i < m; i++)
        {
            inputs = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
            path.Add(Board.Grid[inputs[1], inputs[0]]);
        }
        Board.Path = path.ToArray();

        Board board = new Board() { Current = path[0], NextTarget = 1 };
        List<Board> beam = new List<Board> { board };
        Stopwatch sw = Stopwatch.StartNew();
        int beamWidth = 500;
        HashSet<Board> past = new HashSet<Board> { board };
        int expanded = 0;
        for (int depth = 1; ; depth++)
        {
            HashSet<Board> next = new HashSet<Board>();
            foreach (Board b in beam)
            {
                foreach (Board b2 in b.Expand())
                {
                    expanded++;
                    if (past.Add(b2)) next.Add(b2);
                }
            }
            beam = next.OrderByDescending(n => n.Score()).Take(beamWidth).ToList();
            int time = (int)sw.ElapsedMilliseconds;
            double shallExpand = (double)expanded / time * (TIME_LIMIT - time);
            beamWidth = (int)(shallExpand / (220.0 - depth) / 6.5);
            beamWidth = Math.Max(beamWidth, 100);
            beamWidth = Math.Min(beamWidth, 1000);
            if (beam[0].NextTarget == m)
            {
                foreach (string a in beam[0].GetActions()) Console.WriteLine(a);
                break;
            }
        }
        Console.Error.WriteLine(beam[0].GetActions().Count + "   - " + sw.ElapsedMilliseconds + " ms");
    }
}

public enum ActionType
{
    Move,
    Slide,
    Alter
}

public class Board : IEquatable<Board>
{
    public static int Size;
    public static int Area => Size * Size;
    public static Cell[,] Grid;
    public static Cell[] Path;
    public List<Cell> Block;
    public Board Parent;
    public int ActionDir;
    public ActionType ActionType;
    public Cell Current;
    public int NextTarget;
    public long Hash;

    public Board()
    {
        Block = new List<Cell>();
    }

    public static void InitBoard()
    {
        Grid = new Cell[Board.Size, Board.Size];
        for (int y = 0; y < Size; y++)
        {
            for (int x = 0; x < Size; x++) Grid[x, y] = new Cell(x, y);
        }
        foreach (Cell cell in Grid) cell.MakeNeighbors(Grid);
        foreach (Cell cell in Grid) cell.MakeCloseCells();
    }

    public Board(Board parent, int dir, ActionType actionType, Cell targetCell)
    {
        this.Parent = parent;
        this.ActionDir = dir;
        this.ActionType = actionType;
        this.Block = parent.Block;
        this.NextTarget = parent.NextTarget;
        this.Hash = parent.Hash;
        if (actionType == ActionType.Alter)
        {
            Block = new List<Cell>(Block);
            Current = parent.Current;
            if (Block.Contains(targetCell)) Block.Remove(targetCell);
            else Block.Add(targetCell);
            Hash ^= targetCell.WallHash;
        }
        else
        {
            Current = targetCell;
            if (Current == Path[NextTarget]) NextTarget++;
            Hash ^= this.Current.PositionHash ^ parent.Current.PositionHash ^ NextTarget ^ parent.NextTarget;
        }
    }

    public IEnumerable<Board> Expand()
    {
        for (int dir = 0; dir < 4; dir++)
        {
            Cell next = Current.Neighbors[dir];
            if (next == null) continue;
            yield return new Board(this, dir, ActionType.Alter, next);
            if (Block.Contains(next)) continue;
            yield return new Board(this, dir, ActionType.Move, next);
            while (next.Neighbors[dir] != null && !Block.Contains(next.Neighbors[dir])) next = next.Neighbors[dir];
            yield return new Board(this, dir, ActionType.Slide, next);
        }
    }

    public List<string> GetActions()
    {
        List<string> result = new List<string>();
        Board b = this;
        while (b.Parent != null)
        {
            result.Add(b.ActionType.ToString()[0] + " " + "DRUL"[b.ActionDir]);
            b = b.Parent;
        }
        result.Reverse();
        return result;
    }

    private static Dictionary<long, double> blockLookup = new Dictionary<long, double>();
    public double Score()
    {
        double result = 1000 * NextTarget;
        if (NextTarget < Path.Length) result -= Current.Dist(Path[NextTarget]);
        long blockKey = Hash ^ Current.PositionHash;
        if (blockLookup.ContainsKey(blockKey)) result += blockLookup[blockKey];
        else
        {
            double factor = 1;
            double blockScore = 0;
            for (int t = NextTarget; t < Path.Length; t++)
            {
                Cell target = Path[t];
                if (Block.Contains(target)) blockScore--;
                int dist = target.Dist(target.CloseCells.Last());
                foreach (Cell b in Block) dist = Math.Min(dist, b.Dist(target));
                blockScore -= factor * dist;
                factor *= 0.99;
            }
            blockLookup[blockKey] = blockScore;
            result += blockScore;
        }
        return result;
    }

    public override int GetHashCode() => Hash.GetHashCode();

    public bool Equals(Board board) => this.Hash == board.Hash;
}

public class Cell
{
    public int X;
    public int Y;
    public int ID => X * Board.Size + Y;
    public Cell[] Neighbors = new Cell[4];
    public Cell[] CloseCells;
    private static Random random = new Random(0);
    public long PositionHash;
    public long WallHash;
    public Cell(int x, int y)
    {
        this.X = x;
        this.Y = y;
        PositionHash = random.NextInt64();
        WallHash = random.NextInt64();
    }

    private static int[] dx = { 0, 1, 0, -1 };
    private static int[] dy = { 1, 0, -1, 0 };

    public void MakeNeighbors(Cell[,] grid)
    {
        for (int dir = 0; dir < dx.Length; dir++)
        {
            int x = this.X + dx[dir];
            int y = this.Y + dy[dir];
            if (x >= 0 && x < Board.Size && y >= 0 && y < Board.Size) Neighbors[dir] = grid[x, y];
        }
    }

    public void MakeCloseCells()
    {
        List<Cell> close = new List<Cell>();
        Queue<Cell> queue = new Queue<Cell>();
        bool[] visited = new bool[Board.Area];
        queue.Enqueue(this);
        visited[this.ID] = true;
        while (true)
        {
            Cell c = queue.Dequeue();
            foreach (Cell n in c.Neighbors)
            {
                if (n == null) goto stopLoop;
                if (visited[n.ID]) continue;
                close.Add(n);
                queue.Enqueue(n);
            }
        }
    stopLoop:
        if (close.Count == 0) close.Add(Neighbors.First(n => n != null));
        CloseCells = close.ToArray();
    }

    public int Dist(Cell cell)
    {
        return Math.Abs(X - cell.X) + Math.Abs(Y - cell.Y);
    }

    public override string ToString()
    {
        return $"({X}/{Y})";
    }
}

Submission Info

Submission Time
Task A - Skating with Blocks
User eulerscheZahl
Language C# 11.0 (.NET 7.0.7)
Score 214994
Code Size 7675 Byte
Status AC
Exec Time 1968 ms
Memory 246240 KiB

Judge Result

Set Name test_ALL
Score / Max Score 214994 / 246000
Status
AC × 150
Set Name Test Cases
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt, test_0100.txt, test_0101.txt, test_0102.txt, test_0103.txt, test_0104.txt, test_0105.txt, test_0106.txt, test_0107.txt, test_0108.txt, test_0109.txt, test_0110.txt, test_0111.txt, test_0112.txt, test_0113.txt, test_0114.txt, test_0115.txt, test_0116.txt, test_0117.txt, test_0118.txt, test_0119.txt, test_0120.txt, test_0121.txt, test_0122.txt, test_0123.txt, test_0124.txt, test_0125.txt, test_0126.txt, test_0127.txt, test_0128.txt, test_0129.txt, test_0130.txt, test_0131.txt, test_0132.txt, test_0133.txt, test_0134.txt, test_0135.txt, test_0136.txt, test_0137.txt, test_0138.txt, test_0139.txt, test_0140.txt, test_0141.txt, test_0142.txt, test_0143.txt, test_0144.txt, test_0145.txt, test_0146.txt, test_0147.txt, test_0148.txt, test_0149.txt
Case Name Status Exec Time Memory
test_0000.txt AC 1823 ms 210720 KiB
test_0001.txt AC 1853 ms 209320 KiB
test_0002.txt AC 1836 ms 235456 KiB
test_0003.txt AC 1899 ms 213992 KiB
test_0004.txt AC 1805 ms 215068 KiB
test_0005.txt AC 1718 ms 234896 KiB
test_0006.txt AC 1814 ms 202280 KiB
test_0007.txt AC 1876 ms 239568 KiB
test_0008.txt AC 1913 ms 227676 KiB
test_0009.txt AC 1793 ms 224784 KiB
test_0010.txt AC 1968 ms 236416 KiB
test_0011.txt AC 1867 ms 232588 KiB
test_0012.txt AC 1748 ms 224876 KiB
test_0013.txt AC 1759 ms 238576 KiB
test_0014.txt AC 1776 ms 230924 KiB
test_0015.txt AC 1863 ms 233944 KiB
test_0016.txt AC 1780 ms 228460 KiB
test_0017.txt AC 1838 ms 205456 KiB
test_0018.txt AC 1731 ms 234872 KiB
test_0019.txt AC 1845 ms 229064 KiB
test_0020.txt AC 1892 ms 232364 KiB
test_0021.txt AC 1862 ms 215868 KiB
test_0022.txt AC 1889 ms 245592 KiB
test_0023.txt AC 1871 ms 209800 KiB
test_0024.txt AC 1738 ms 226716 KiB
test_0025.txt AC 1829 ms 207820 KiB
test_0026.txt AC 1844 ms 226440 KiB
test_0027.txt AC 1892 ms 233888 KiB
test_0028.txt AC 1799 ms 226668 KiB
test_0029.txt AC 1853 ms 237668 KiB
test_0030.txt AC 1743 ms 231600 KiB
test_0031.txt AC 1797 ms 229360 KiB
test_0032.txt AC 1810 ms 224184 KiB
test_0033.txt AC 1779 ms 225880 KiB
test_0034.txt AC 1881 ms 218828 KiB
test_0035.txt AC 1776 ms 232556 KiB
test_0036.txt AC 1771 ms 231104 KiB
test_0037.txt AC 1827 ms 235840 KiB
test_0038.txt AC 1878 ms 229792 KiB
test_0039.txt AC 1922 ms 229416 KiB
test_0040.txt AC 1842 ms 233348 KiB
test_0041.txt AC 1759 ms 231492 KiB
test_0042.txt AC 1843 ms 227820 KiB
test_0043.txt AC 1700 ms 226516 KiB
test_0044.txt AC 1821 ms 225392 KiB
test_0045.txt AC 1778 ms 234148 KiB
test_0046.txt AC 1822 ms 231968 KiB
test_0047.txt AC 1772 ms 230428 KiB
test_0048.txt AC 1850 ms 229536 KiB
test_0049.txt AC 1783 ms 232808 KiB
test_0050.txt AC 1816 ms 229172 KiB
test_0051.txt AC 1833 ms 229716 KiB
test_0052.txt AC 1952 ms 246240 KiB
test_0053.txt AC 1682 ms 230328 KiB
test_0054.txt AC 1884 ms 232872 KiB
test_0055.txt AC 1765 ms 229412 KiB
test_0056.txt AC 1887 ms 231032 KiB
test_0057.txt AC 1833 ms 228648 KiB
test_0058.txt AC 1896 ms 208216 KiB
test_0059.txt AC 1865 ms 228504 KiB
test_0060.txt AC 1797 ms 226460 KiB
test_0061.txt AC 1783 ms 225456 KiB
test_0062.txt AC 1760 ms 227552 KiB
test_0063.txt AC 1801 ms 232908 KiB
test_0064.txt AC 1848 ms 228768 KiB
test_0065.txt AC 1831 ms 233488 KiB
test_0066.txt AC 1896 ms 224456 KiB
test_0067.txt AC 1882 ms 230048 KiB
test_0068.txt AC 1781 ms 228404 KiB
test_0069.txt AC 1802 ms 231136 KiB
test_0070.txt AC 1786 ms 228652 KiB
test_0071.txt AC 1838 ms 235120 KiB
test_0072.txt AC 1804 ms 236448 KiB
test_0073.txt AC 1795 ms 227388 KiB
test_0074.txt AC 1734 ms 226632 KiB
test_0075.txt AC 1817 ms 231844 KiB
test_0076.txt AC 1795 ms 231724 KiB
test_0077.txt AC 1823 ms 205216 KiB
test_0078.txt AC 1861 ms 215992 KiB
test_0079.txt AC 1862 ms 228860 KiB
test_0080.txt AC 1845 ms 231480 KiB
test_0081.txt AC 1761 ms 231100 KiB
test_0082.txt AC 1797 ms 225056 KiB
test_0083.txt AC 1752 ms 223800 KiB
test_0084.txt AC 1761 ms 235664 KiB
test_0085.txt AC 1860 ms 236272 KiB
test_0086.txt AC 1748 ms 232964 KiB
test_0087.txt AC 1824 ms 223884 KiB
test_0088.txt AC 1850 ms 210844 KiB
test_0089.txt AC 1846 ms 231112 KiB
test_0090.txt AC 1838 ms 238996 KiB
test_0091.txt AC 1817 ms 228420 KiB
test_0092.txt AC 1912 ms 212120 KiB
test_0093.txt AC 1892 ms 234168 KiB
test_0094.txt AC 1806 ms 220500 KiB
test_0095.txt AC 1808 ms 207284 KiB
test_0096.txt AC 1882 ms 233256 KiB
test_0097.txt AC 1847 ms 229840 KiB
test_0098.txt AC 1809 ms 225472 KiB
test_0099.txt AC 1814 ms 224072 KiB
test_0100.txt AC 1750 ms 232916 KiB
test_0101.txt AC 1721 ms 230444 KiB
test_0102.txt AC 1966 ms 233912 KiB
test_0103.txt AC 1762 ms 223588 KiB
test_0104.txt AC 1903 ms 224468 KiB
test_0105.txt AC 1784 ms 232144 KiB
test_0106.txt AC 1867 ms 204548 KiB
test_0107.txt AC 1781 ms 226124 KiB
test_0108.txt AC 1875 ms 203156 KiB
test_0109.txt AC 1839 ms 228808 KiB
test_0110.txt AC 1777 ms 221240 KiB
test_0111.txt AC 1910 ms 212988 KiB
test_0112.txt AC 1844 ms 235708 KiB
test_0113.txt AC 1912 ms 229660 KiB
test_0114.txt AC 1817 ms 239072 KiB
test_0115.txt AC 1808 ms 232368 KiB
test_0116.txt AC 1847 ms 231740 KiB
test_0117.txt AC 1830 ms 231240 KiB
test_0118.txt AC 1930 ms 204888 KiB
test_0119.txt AC 1826 ms 232104 KiB
test_0120.txt AC 1826 ms 227720 KiB
test_0121.txt AC 1830 ms 233276 KiB
test_0122.txt AC 1738 ms 230012 KiB
test_0123.txt AC 1860 ms 232012 KiB
test_0124.txt AC 1766 ms 222344 KiB
test_0125.txt AC 1745 ms 225420 KiB
test_0126.txt AC 1773 ms 225532 KiB
test_0127.txt AC 1790 ms 203680 KiB
test_0128.txt AC 1883 ms 224152 KiB
test_0129.txt AC 1737 ms 213588 KiB
test_0130.txt AC 1845 ms 231052 KiB
test_0131.txt AC 1770 ms 204816 KiB
test_0132.txt AC 1838 ms 231808 KiB
test_0133.txt AC 1849 ms 232948 KiB
test_0134.txt AC 1850 ms 227084 KiB
test_0135.txt AC 1856 ms 233092 KiB
test_0136.txt AC 1832 ms 206264 KiB
test_0137.txt AC 1828 ms 238728 KiB
test_0138.txt AC 1755 ms 225872 KiB
test_0139.txt AC 1890 ms 212460 KiB
test_0140.txt AC 1851 ms 230484 KiB
test_0141.txt AC 1813 ms 224816 KiB
test_0142.txt AC 1836 ms 228536 KiB
test_0143.txt AC 1800 ms 227540 KiB
test_0144.txt AC 1865 ms 233244 KiB
test_0145.txt AC 1786 ms 225336 KiB
test_0146.txt AC 1818 ms 228292 KiB
test_0147.txt AC 1793 ms 207016 KiB
test_0148.txt AC 1828 ms 228572 KiB
test_0149.txt AC 1831 ms 210068 KiB