Submission #68709741
Source Code Expand
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Formats.Asn1;
using System.Linq;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Text;
public class Solution
{
public const int TIME_LIMIT = 1700;
private static Random random = new Random(0);
public static void Main()
{
int[] inputs = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
Stopwatch sw = Stopwatch.StartNew();
Board.Size = inputs[0];
int m = inputs[1];
int k = inputs[2];
Board.InitGrid();
Board board = new Board();
board.Robots = Enumerable.Range(0, m).Select(i => new Robot { ID = i }).ToList();
board.Waxed = new bool[Board.Size * Board.Size];
Robot.RobotActions = Enumerable.Range(0, m).Select(i => new int[k]).ToArray();
foreach (Robot r in board.Robots)
{
inputs = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
r.Location = Board.Grid[inputs[1], inputs[0]];
board.Waxed[r.Location.ID] = true;
}
board.WaxedCount = board.Waxed.Count(b => b);
for (int y = 0; y < Board.Size; y++)
{
string line = Console.ReadLine();
for (int x = 0; x < line.Length; x++)
{
if (line[x] == '1')
{
Board.Grid[x, y].Neighbors[0] = Board.Grid[x, y];
Board.Grid[x + 1, y].Neighbors[2] = Board.Grid[x + 1, y];
}
}
}
for (int y = 0; y < Board.Size - 1; y++)
{
string line = Console.ReadLine();
for (int x = 0; x < line.Length; x++)
{
if (line[x] == '1')
{
Board.Grid[x, y].Neighbors[1] = Board.Grid[x, y];
Board.Grid[x, y + 1].Neighbors[3] = Board.Grid[x, y + 1];
}
}
}
Board.InitDistances();
string actionString = "RDLUS";
InitActions(board);
Board solution = WaxBoard(board, null);
Console.Error.WriteLine("initial solution: " + solution.Depth + " @" + sw.ElapsedMilliseconds + " ms");
HashSet<Board> revertedTo = new();
while (sw.ElapsedMilliseconds < TIME_LIMIT)
{
Board prev = solution.Parent;
Cell lastFill = null;
foreach (Cell c in Board.Grid)
{
if (!prev.Waxed[c.ID]) lastFill = c;
}
Board b = board;
while (prev.Parent != null)
{
if (prev.Robots.Any(r => r.Location.Neighbors.Contains(lastFill))) b = prev;
prev = prev.Parent;
}
if (!revertedTo.Add(b))
{
b = board;
for (int i = 0; i < 5; i++) b = board.Expand().OrderBy(b => random.NextDouble()).First();
}
else if (b != board) b = b.Expand().First(e => e.Waxed[lastFill.ID]);
Console.Error.WriteLine(sw.ElapsedMilliseconds + "ms: revert to " + b.Depth);
Board refill = WaxBoard(b, sw);
Console.Error.WriteLine("refill length: " + refill?.Depth);
if (refill != null && refill.Depth < solution.Depth)
{
Console.Error.WriteLine("shorten: " + solution.Depth + " => " + refill.Depth);
solution = refill;
}
}
// try to fill last cell with different action
bool improved = true;
while (improved)
{
improved = false;
Board prev = solution.Parent;
Cell lastFill = null;
foreach (Cell c in Board.Grid)
{
if (!prev.Waxed[c.ID]) lastFill = c;
}
List<Board> candidates = new();
List<Board> path = new();
while (prev.Parent != null)
{
path.Add(prev);
if (prev.Robots.Any(r => r.Location.Neighbors.Contains(lastFill))) candidates.Add(prev);
prev = prev.Parent;
}
path.Add(prev);
path.Reverse();
foreach (Board c in candidates.Reverse<Board>())
{
foreach (Robot r in c.Robots.Where(ro => ro.Location.Neighbors.Contains(lastFill)))
{
int a1 = r.Location.Neighbors.ToList().IndexOf(lastFill);
int a2 = lastFill.Neighbors.ToList().IndexOf(r.Location);
List<int> a1Cand = Enumerable.Range(0, k).Where(i => r.Actions[i] == a1).ToList();
List<int> a2Cand = Enumerable.Range(0, k).Where(i => r.Actions[i] == a2).ToList();
foreach (int a1Take in a2Cand)
{
foreach (int a2Take in a1Cand)
{
Board inserted = InsertAction(c, path, r, a1Take, a2Take);
if (inserted != null && inserted.Depth < solution.Depth)
{
Console.Error.WriteLine("postprecessing: " + solution.Depth + " => " + inserted.Depth);
improved = true;
solution = inserted;
goto hasImproved;
}
}
}
List<int> empty = Enumerable.Range(0, k).Where(i => r.Actions[i] == 4).ToList();
for (int e = 0; e + 1 < empty.Count; e += 2)
{
r.Actions[empty[e]] = a1;
r.Actions[empty[e + 1]] = a2;
Board inserted = InsertAction(c, path, r, empty[e], empty[e + 1]);
if (inserted != null && inserted.Depth < solution.Depth)
{
Console.Error.WriteLine("postprecessing: " + solution.Depth + " => " + inserted.Depth);
improved = true;
solution = inserted;
goto hasImproved;
}
else
{
r.Actions[empty[e]] = 4;
r.Actions[empty[e + 1]] = 4;
}
}
}
}
hasImproved:;
}
for (int actionId = 0; actionId < k; actionId++)
{
Console.WriteLine(string.Join(" ", solution.Robots.Select(r => actionString[r.Actions[actionId]])));
}
List<int> actions = new();
while (solution.Parent != null)
{
actions.Add(solution.Action);
solution = solution.Parent;
}
actions.Reverse();
foreach (int a in actions) Console.WriteLine(a);
}
private static Board InsertAction(Board board, List<Board> path, Robot r, int action1, int action2)
{
int index = path.IndexOf(board);
Board result = path[0];
for (int i = 1; i <= index; i++) result = new Board(result, path[i].Action);
result = new Board(result, action1);
result = new Board(result, action2);
for (int i = index + 1; i < path.Count; i++) result = new Board(result, path[i].Action);
if (result.WaxedCount != Board.Size * Board.Size) return null;
while (result.Parent.WaxedCount == Board.Size * Board.Size) result = result.Parent;
return result;
}
private static Board WaxBoard(Board board, Stopwatch sw)
{
List<Board> beam = new() { board };
for (int depth = 1; sw == null || sw.ElapsedMilliseconds < TIME_LIMIT; depth++)
{
beam = beam.SelectMany(b => b.Expand()).OrderByDescending(b => 0.01 * random.NextDouble() + b.Score()).Take(3).ToList();
if (beam[0].WaxedCount == Board.Size * Board.Size) return beam[0];
}
return null;
}
private static void InitActions(Board board)
{
foreach (Robot r in board.Robots)
{
while (r.Actions.Distinct().Count() < 4)
{
for (int i = 0; i < r.Actions.Length; i++) r.Actions[i] = Math.Min(i, 4);
//for (int i = 0; i < r.Actions.Length; i++) r.Actions[i] = random.Next(4);// Math.Min(i, 4);
}
}
}
}
public class Board
{
public static int Size;
public List<Robot> Robots = new();
public static Cell[,] Grid;
public bool[] Waxed;
public int WaxedCount;
public Board Parent;
public int Action;
public int Depth;
public Board() { }
public Board(Board parent, int action)
{
this.Parent = parent;
this.Action = action;
this.Depth = parent.Depth + 1;
this.WaxedCount = parent.WaxedCount;
this.Waxed = parent.Waxed.ToArray();
this.Robots = parent.Robots.Select(r => new Robot(r, action)).ToList();
foreach (Robot r in Robots)
{
if (!Waxed[r.Location.ID])
{
Waxed[r.Location.ID] = true;
WaxedCount++;
}
}
}
public static void InitGrid()
{
Grid = new Cell[Board.Size, Board.Size];
for (int x = 0; x < Board.Size; x++)
{
for (int y = 0; y < Board.Size; y++)
{
Grid[x, y] = new Cell(x, y);
}
}
foreach (Cell cell in Grid) cell.InitNeighbors(Grid);
}
public static void InitDistances()
{
foreach (Cell cell in Grid) cell.InitDistances();
}
public IEnumerable<Board> Expand()
{
for (int i = 0; i < 4; i++)
{
yield return new Board(this, i);
}
}
public double Score()
{
double result = 1e6 * WaxedCount;
result += 0.3 * Robots.Select(r => r.Location).Distinct().Count();
int closest = 1000;
foreach (Cell c in Board.Grid)
{
if (!Waxed[c.ID])
{
closest = Math.Min(closest, Robots.Min(r => r.Location.Dist[c.ID]));
int openNeighbors = c.DistinctNeighbors.Count(n => !Waxed[n.ID]);
if (openNeighbors == 0) result -= 3;
else if (openNeighbors == 1) result -= 1;
}
}
foreach (Robot r in Robots)
{
int unwaxedNeighbors = r.Location.DistinctNeighbors.Count(n => !Waxed[n.ID]);
if (unwaxedNeighbors > 0) result += 0.01 * (4 - unwaxedNeighbors);
}
result -= closest;
return result;
}
}
public class Robot
{
public int ID;
public Cell Location;
public static int[][] RobotActions;
public int[] Actions => RobotActions[ID];
public Robot() { }
public Robot(Robot r, int action)
{
this.ID = r.ID;
this.Location = r.Location.Neighbors[Actions[action]];
}
public override string ToString() => ID + ": " + Location;
}
public class Cell
{
public int X;
public int Y;
public int ID => X + Y * Board.Size;
public Cell[] Neighbors = new Cell[5];
public Cell[] DistinctNeighbors;
public int[] Dist;
public Cell(int x, int y)
{
X = x;
Y = y;
}
private static int[] dx = { 1, 0, -1, 0, 0 };
private static int[] dy = { 0, 1, 0, -1, 0 };
public void InitNeighbors(Cell[,] grid)
{
for (int dir = 0; dir < dx.Length; dir++)
{
int x_ = X + dx[dir];
int y_ = Y + dy[dir];
if (x_ < 0 || x_ >= Board.Size || y_ < 0 || y_ >= Board.Size) Neighbors[dir] = this;
else Neighbors[dir] = grid[x_, y_];
}
DistinctNeighbors = Neighbors.Where(n => n != this).Distinct().ToArray();
}
public void InitDistances()
{
Dist = new int[Board.Size * Board.Size];
Array.Fill(Dist, 10000);
Dist[ID] = 0;
Queue<Cell> queue = new Queue<Cell>();
queue.Enqueue(this);
while (queue.Count > 0)
{
Cell c = queue.Dequeue();
foreach (Cell n in c.Neighbors)
{
if (Dist[n.ID] < 10000) continue;
Dist[n.ID] = 1 + Dist[c.ID];
queue.Enqueue(n);
}
}
}
public override string ToString() => X + "/" + Y;
}
Submission Info
| Submission Time | |
|---|---|
| Task | A - Single Controller Multiple Robots |
| User | eulerscheZahl |
| Language | C# 11.0 (.NET 7.0.7) |
| Score | 354455 |
| Code Size | 12864 Byte |
| Status | AC |
| Exec Time | 1774 ms |
| Memory | 63920 KiB |
Judge Result
| Set Name | test_ALL | ||
|---|---|---|---|
| Score / Max Score | 354455 / 405000 | ||
| Status |
|
| 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 | 1759 ms | 62908 KiB |
| test_0001.txt | AC | 1764 ms | 62964 KiB |
| test_0002.txt | AC | 1760 ms | 62772 KiB |
| test_0003.txt | AC | 1769 ms | 62956 KiB |
| test_0004.txt | AC | 1759 ms | 63108 KiB |
| test_0005.txt | AC | 1764 ms | 62876 KiB |
| test_0006.txt | AC | 1764 ms | 62748 KiB |
| test_0007.txt | AC | 1763 ms | 62856 KiB |
| test_0008.txt | AC | 1763 ms | 63016 KiB |
| test_0009.txt | AC | 1756 ms | 62872 KiB |
| test_0010.txt | AC | 1763 ms | 63260 KiB |
| test_0011.txt | AC | 1774 ms | 62636 KiB |
| test_0012.txt | AC | 1772 ms | 62624 KiB |
| test_0013.txt | AC | 1762 ms | 63092 KiB |
| test_0014.txt | AC | 1762 ms | 63028 KiB |
| test_0015.txt | AC | 1757 ms | 63340 KiB |
| test_0016.txt | AC | 1756 ms | 62732 KiB |
| test_0017.txt | AC | 1756 ms | 63248 KiB |
| test_0018.txt | AC | 1770 ms | 63212 KiB |
| test_0019.txt | AC | 1764 ms | 62668 KiB |
| test_0020.txt | AC | 1758 ms | 62876 KiB |
| test_0021.txt | AC | 1762 ms | 62920 KiB |
| test_0022.txt | AC | 1757 ms | 63244 KiB |
| test_0023.txt | AC | 1764 ms | 62948 KiB |
| test_0024.txt | AC | 1760 ms | 63132 KiB |
| test_0025.txt | AC | 1763 ms | 62788 KiB |
| test_0026.txt | AC | 1762 ms | 62600 KiB |
| test_0027.txt | AC | 1760 ms | 63284 KiB |
| test_0028.txt | AC | 1759 ms | 63356 KiB |
| test_0029.txt | AC | 1768 ms | 63108 KiB |
| test_0030.txt | AC | 1761 ms | 62984 KiB |
| test_0031.txt | AC | 1766 ms | 63000 KiB |
| test_0032.txt | AC | 1757 ms | 62604 KiB |
| test_0033.txt | AC | 1760 ms | 63388 KiB |
| test_0034.txt | AC | 1757 ms | 62692 KiB |
| test_0035.txt | AC | 1764 ms | 62676 KiB |
| test_0036.txt | AC | 1760 ms | 62652 KiB |
| test_0037.txt | AC | 1767 ms | 63156 KiB |
| test_0038.txt | AC | 1752 ms | 62788 KiB |
| test_0039.txt | AC | 1752 ms | 62736 KiB |
| test_0040.txt | AC | 1764 ms | 63432 KiB |
| test_0041.txt | AC | 1761 ms | 62948 KiB |
| test_0042.txt | AC | 1759 ms | 62604 KiB |
| test_0043.txt | AC | 1756 ms | 62884 KiB |
| test_0044.txt | AC | 1762 ms | 62708 KiB |
| test_0045.txt | AC | 1762 ms | 62956 KiB |
| test_0046.txt | AC | 1756 ms | 62860 KiB |
| test_0047.txt | AC | 1766 ms | 62648 KiB |
| test_0048.txt | AC | 1759 ms | 63136 KiB |
| test_0049.txt | AC | 1760 ms | 63920 KiB |
| test_0050.txt | AC | 1761 ms | 63184 KiB |
| test_0051.txt | AC | 1761 ms | 63256 KiB |
| test_0052.txt | AC | 1770 ms | 62948 KiB |
| test_0053.txt | AC | 1766 ms | 62564 KiB |
| test_0054.txt | AC | 1760 ms | 62656 KiB |
| test_0055.txt | AC | 1762 ms | 63192 KiB |
| test_0056.txt | AC | 1765 ms | 62688 KiB |
| test_0057.txt | AC | 1760 ms | 63068 KiB |
| test_0058.txt | AC | 1762 ms | 63000 KiB |
| test_0059.txt | AC | 1753 ms | 62704 KiB |
| test_0060.txt | AC | 1772 ms | 63276 KiB |
| test_0061.txt | AC | 1761 ms | 62764 KiB |
| test_0062.txt | AC | 1759 ms | 62764 KiB |
| test_0063.txt | AC | 1764 ms | 63052 KiB |
| test_0064.txt | AC | 1762 ms | 63076 KiB |
| test_0065.txt | AC | 1758 ms | 63000 KiB |
| test_0066.txt | AC | 1753 ms | 63428 KiB |
| test_0067.txt | AC | 1757 ms | 63064 KiB |
| test_0068.txt | AC | 1762 ms | 62824 KiB |
| test_0069.txt | AC | 1766 ms | 62788 KiB |
| test_0070.txt | AC | 1763 ms | 62884 KiB |
| test_0071.txt | AC | 1760 ms | 63092 KiB |
| test_0072.txt | AC | 1762 ms | 62776 KiB |
| test_0073.txt | AC | 1763 ms | 63152 KiB |
| test_0074.txt | AC | 1761 ms | 62960 KiB |
| test_0075.txt | AC | 1760 ms | 63076 KiB |
| test_0076.txt | AC | 1757 ms | 63304 KiB |
| test_0077.txt | AC | 1759 ms | 63236 KiB |
| test_0078.txt | AC | 1761 ms | 62912 KiB |
| test_0079.txt | AC | 1754 ms | 63176 KiB |
| test_0080.txt | AC | 1764 ms | 62872 KiB |
| test_0081.txt | AC | 1763 ms | 63048 KiB |
| test_0082.txt | AC | 1763 ms | 63512 KiB |
| test_0083.txt | AC | 1759 ms | 63164 KiB |
| test_0084.txt | AC | 1760 ms | 63088 KiB |
| test_0085.txt | AC | 1763 ms | 62712 KiB |
| test_0086.txt | AC | 1762 ms | 62700 KiB |
| test_0087.txt | AC | 1757 ms | 62964 KiB |
| test_0088.txt | AC | 1760 ms | 63148 KiB |
| test_0089.txt | AC | 1755 ms | 62828 KiB |
| test_0090.txt | AC | 1773 ms | 63372 KiB |
| test_0091.txt | AC | 1766 ms | 62964 KiB |
| test_0092.txt | AC | 1762 ms | 62792 KiB |
| test_0093.txt | AC | 1760 ms | 63240 KiB |
| test_0094.txt | AC | 1761 ms | 63188 KiB |
| test_0095.txt | AC | 1757 ms | 62744 KiB |
| test_0096.txt | AC | 1769 ms | 63160 KiB |
| test_0097.txt | AC | 1759 ms | 62744 KiB |
| test_0098.txt | AC | 1766 ms | 63136 KiB |
| test_0099.txt | AC | 1766 ms | 62616 KiB |
| test_0100.txt | AC | 1759 ms | 63168 KiB |
| test_0101.txt | AC | 1756 ms | 62960 KiB |
| test_0102.txt | AC | 1764 ms | 62772 KiB |
| test_0103.txt | AC | 1762 ms | 62972 KiB |
| test_0104.txt | AC | 1760 ms | 62804 KiB |
| test_0105.txt | AC | 1764 ms | 63092 KiB |
| test_0106.txt | AC | 1759 ms | 63204 KiB |
| test_0107.txt | AC | 1756 ms | 62544 KiB |
| test_0108.txt | AC | 1757 ms | 62700 KiB |
| test_0109.txt | AC | 1763 ms | 62788 KiB |
| test_0110.txt | AC | 1758 ms | 63116 KiB |
| test_0111.txt | AC | 1761 ms | 63256 KiB |
| test_0112.txt | AC | 1761 ms | 63016 KiB |
| test_0113.txt | AC | 1758 ms | 63228 KiB |
| test_0114.txt | AC | 1762 ms | 63140 KiB |
| test_0115.txt | AC | 1769 ms | 62920 KiB |
| test_0116.txt | AC | 1754 ms | 63068 KiB |
| test_0117.txt | AC | 1764 ms | 63180 KiB |
| test_0118.txt | AC | 1760 ms | 63008 KiB |
| test_0119.txt | AC | 1757 ms | 63372 KiB |
| test_0120.txt | AC | 1751 ms | 63136 KiB |
| test_0121.txt | AC | 1761 ms | 62924 KiB |
| test_0122.txt | AC | 1762 ms | 63440 KiB |
| test_0123.txt | AC | 1769 ms | 62904 KiB |
| test_0124.txt | AC | 1772 ms | 63412 KiB |
| test_0125.txt | AC | 1773 ms | 63424 KiB |
| test_0126.txt | AC | 1766 ms | 62768 KiB |
| test_0127.txt | AC | 1757 ms | 62840 KiB |
| test_0128.txt | AC | 1762 ms | 63204 KiB |
| test_0129.txt | AC | 1758 ms | 62816 KiB |
| test_0130.txt | AC | 1762 ms | 63092 KiB |
| test_0131.txt | AC | 1761 ms | 62664 KiB |
| test_0132.txt | AC | 1759 ms | 63176 KiB |
| test_0133.txt | AC | 1766 ms | 62500 KiB |
| test_0134.txt | AC | 1758 ms | 63104 KiB |
| test_0135.txt | AC | 1761 ms | 62688 KiB |
| test_0136.txt | AC | 1758 ms | 62916 KiB |
| test_0137.txt | AC | 1760 ms | 62988 KiB |
| test_0138.txt | AC | 1757 ms | 62752 KiB |
| test_0139.txt | AC | 1750 ms | 63304 KiB |
| test_0140.txt | AC | 1765 ms | 62744 KiB |
| test_0141.txt | AC | 1767 ms | 63220 KiB |
| test_0142.txt | AC | 1758 ms | 63072 KiB |
| test_0143.txt | AC | 1760 ms | 63136 KiB |
| test_0144.txt | AC | 1768 ms | 62756 KiB |
| test_0145.txt | AC | 1763 ms | 63704 KiB |
| test_0146.txt | AC | 1755 ms | 63280 KiB |
| test_0147.txt | AC | 1753 ms | 62784 KiB |
| test_0148.txt | AC | 1765 ms | 63016 KiB |
| test_0149.txt | AC | 1757 ms | 62744 KiB |