2010-01-14

http://anond.hatelabo.jp/20100113192313

これで40分。

タイムアタックってことでアルゴリズムは全幅探索で書き上げました。

エラーチェック皆無。

A*ならもう5分ほど延びるかな?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Maze
{
    class Program
    {
        // 探索用地図
        static int[,] maze;

        // 始点終点
        static Position Start = new Position(0, 0), Goal = new Position(0, 0);

        static void Main(string[] args)
        {
            //////////////////////////// まずは各行のリストとして読み込み
            string[] inMaze;

            using (var fp = new FileStream(args[0], FileMode.Open, FileAccess.Read))
            using (var iStream = new StreamReader(fp))
                inMaze = iStream.ReadToEnd().Split('\n');

            // 迷路幅
            int height = inMaze.Length;

            // 迷路高さ
            int width = inMaze[0].Length;

            /////////////////////////// 読み込んだ迷路を作業用地図に展開
            maze = new int[width, height];
            for (int y = 0; y < height; ++y)
            {
                string line = inMaze[y];
                for (int x = 0; x < line.Length; ++x)
                {
                    maze[x, y] = line[x] == '*'
                        ? -1
                        : 0;
                    if (line[x] == 'S') Start = new Position(x, y);
                    if (line[x] == 'G') Goal = new Position(x, y);
                }
            }

            // 探索実行
            int dist = Search(maze, Start);

            // 探索結果から最短経路を再現
            Position backTracer = Goal;
            while (dist&gt;1){
                --dist;
                backTracer = backTracer.Nearbys.First(pos =&gt; maze[pos.X,pos.Y] == dist);
                maze[backTracer.X, backTracer.Y] = -2;
            }

            //////////////////// 最短経路こみのアスキー地図に変換
            char[,] outMaze = new char[width, height];

            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    outMaze[x, y] = maze[x, y] == -2
                        ? '$'
                        : maze[x, y] == -1
                            ? '*'
                            : ' ';
                }
            }
            outMaze[Start.X, Start.Y] = 'S';
            outMaze[Goal.X, Goal.Y] = 'G';


            ////////////////////// 結果は標準出力に。
            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                    Console.Write(outMaze[x, y]);
                Console.WriteLine();
            }
            Console.ReadLine();
        }

        /// <summary&gt;
        /// 探索する。SG間の道のりを返す(道のり=SGが隣接しているなら1)
        /// </summary&gt;
        private static int Search(int[,] maze, Position Start)
        {
            List<Position&gt; FrontLine = new List<Position&gt;();
            FrontLine.Add(Start);
            int dist = 1;
            for (; ; )
            {
                List<Position&gt; NextFrontLine = new List<Position&gt;();
                foreach (var pos in FrontLine)
                {
                    foreach (var nextPos in pos.Nearbys)
                    {
                        if (nextPos == Goal) return dist;
                        if (maze[nextPos.X, nextPos.Y] == 0)
                        {
                            maze[nextPos.X, nextPos.Y] = dist;
                            NextFrontLine.Add(nextPos);
                        }
                    }
                }
                FrontLine = NextFrontLine;
                ++dist;
            }
        }
    }

    struct Position
    {
        public readonly int X, Y;
        public Position(int x, int y) { X = x; Y = y; }

        public IEnumerable<Position&gt; Nearbys
        {
            get
            {
                return new[]{
                    new Position(X-1,Y),
                    new Position(X,Y-1),
                    new Position(X+1,Y),
                    new Position(X,Y+1),
                };
            }
        }

        public static bool operator==(Position p1, Position p2){
            return p1.X == p2.X &amp;&amp; p1.Y == p2.Y;
        }

        public static bool operator!=(Position p1, Position p2){
            return p1.X != p2.X || p1.Y != p2.Y;
        }
    }
}
記事への反応 -
  • 少し遅れた感があるけど、解いてみた。 出力がテキストでないけど・・・。 仕事の合間を使ってやったものの、昼前に始めたのが5時頃にようやくできる程度。 これを25分とは尋常じゃ...

    • これで40分。 タイムアタックってことでアルゴリズムは全幅探索で書き上げました。 エラーチェック皆無。 A*ならもう5分ほど延びるかな? using System;using System.Collections.Generic;using System.L...

      • [増田@hatelabo.jp]gmcs test.cs -r:System.Xml.Linq -out:test.exe test.cs(108,12): warning CS0660: `Maze.Position' defines operator == or operator != but does not override Object.Equals(object o) test.cs(108,12): warning CS0661: `Maze.Position' define...

      • なんか、経路問題だけあって、できてる人のほうが多い印象だよね。 所詮プログラムなんだから、普通にだれでもできるよねぇ。 所詮やっぱり、プログラマはブルーワーカーか アルゴ...

    • そうは言っても、やっぱりあいつは偉そうだけどね。 こんなプログラムできなくても仕事にはなんの問題もないよ。

    • コンピュータサイエンスの教育を受けた人や、ACM/ICPCとかtop coderとかやってる人なら、このての問題はすぐ解けるよ 解けない(問題を知らない、解きかたを知らない)と、はずかしいレ...

      • 増田のelegantな解答を拝見したい

        • 34分 現役のときに比べて腕が鈍ってるなあ ソースは汚いよ 同じところを二回訪れないことに注意して、次の状態をキューに入れていけばいいだけ 隣は距離1なのでただのFIFOでいい 重み...

          • ワープあり迷宮とかだったらもっと楽しかったのにw

            • 単純にグラフ作ってdijkstraで解けるような拡張だとつまらない 入力のサイズが大きすぎて、普通の解法が通用しなくて、計算量を減らす必要があるとかだと楽しい 例えば、このタイプの...

              • こういう話題を見てると、俺ってつくづくプログラミングそのものには興味が無いなーって思う。 色々小細工してリソースを効率的に使うとか全く興味が無い。どうでもいいから適当に...

                • リソース減らすってのは、技術というより、現実優先なんだよね。 プロダクトを実際に作ると、どうしても、複数のプログラムが一緒に動いていたり、 メモリ減らすとチップを1つ下の...

                  • そういえば、昔、巨大なデーターを扱うプログラムで 遅いというクレームがついて みんなで、早くしましょう。 増田さんの担当分は3時間未満になるようにしてください。って言われ...

                    • その時点ですでに俺のパートは1時間前後だったわけだが。 なら、納期ギリギリまでボケッと遊ぶなり別の勉強するなりして自分の担当分には手を加えず、提出する時に「なんとかが...

              • まずは、巨大な迷路を書くプログラムからだな。 学生時代だったらアルゴリズムを覚えていたので数十分だが いまだと数時間はかかりそう。 とりあえず、巨大な迷路データーが無いこ...

記事への反応(ブックマークコメント)

ログイン ユーザー登録
ようこそ ゲスト さん