結果
| 問題 | No.3 ビットすごろく | 
| コンテスト | |
| ユーザー |  velfare_nagata | 
| 提出日時 | 2016-10-05 14:12:03 | 
| 言語 | C#(csc) (csc 3.9.0) | 
| 結果 | 
                                AC
                                 
                             | 
| 実行時間 | 45 ms / 5,000 ms | 
| コード長 | 3,786 bytes | 
| コンパイル時間 | 961 ms | 
| コンパイル使用メモリ | 113,240 KB | 
| 実行使用メモリ | 25,344 KB | 
| 最終ジャッジ日時 | 2024-07-01 08:07:15 | 
| 合計ジャッジ時間 | 3,080 ms | 
| ジャッジサーバーID (参考情報) | judge5 / judge1 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| other | AC * 33 | 
コンパイルメッセージ
Microsoft (R) Visual C# Compiler version 3.9.0-6.21124.20 (db94f4cc) Copyright (C) Microsoft Corporation. All rights reserved.
ソースコード
using System;
using System.Collections;
namespace CodeIq
{
	internal class Program
	{
		/// <summary>各数値に対応するビットフラグ数のテーブル</summary>
		private static Hashtable _bitCountTable;
		/// <summary>すごろくマス数</summary>
		private static int _n;
		/// <summary>計算要素スタック</summary>
		private static Stack _stack;
		/// <summary>位置に対応する最短手順数</summary>
		private static Hashtable _history;
		/// <summary>現時点での最短手</summary>
		private static int _nowBestOrderCount;
		/// <summary>
		/// Carol は特殊なすごろくをしようとしている。
		/// 
		/// 1からNの番号がふられている一直線に並べられているN個のマスがある。
		/// 1から開始のマスとして、ゴールはNが書かれているマスとする。
		/// 
		/// その場に書かれている数字の2進数で表現した時の1のビット数 だけ「前」または「後」に進めることができる。
		/// (1未満とN+1以上のマスには移動することは出来ない、正確にNにならないとゴールできない)
		/// 
		/// 自然数Nを与えられた時、ゴールに到達できる最短の移動数(開始のマスへも移動にカウントする)を求めてください。
		/// 到達できない場合は-1を出力してください。
		/// 
		/// 開始のマスがすでにゴールになっている場合もあリます。
		/// </summary>
		private static void Main()
		{
			var line = Console.ReadLine();
			//var line = "3";
			if( string.IsNullOrEmpty( line ) )
				return;
			var paramData = line.Split( ' ' );
			_n = int.Parse( paramData[0] );
			_nowBestOrderCount = int.MaxValue;
			_stack = new Stack();
			_stack.Push( 1 );
			_history = new Hashtable();
			_history.Add( 1, 1 );
			var getBitCount = new Func<int, int>( target =>
			{
				var bitCount = 0;
				for( ; target > 0; target &= target - 1 )
					bitCount++;
				return bitCount;
			} );
			_bitCountTable = new Hashtable();
			for( var i = 1; i < _n; i++ )
				_bitCountTable[i] = getBitCount( i );
			for( var i = 1; i <= _n; i++ )
				_history[i] = int.MaxValue;
			// ゴールまでの経路を計算する
			var result = Calculate( 1 );
			//Debug.Print( ( result != int.MaxValue ? result : -1 ).ToString() );
			Console.WriteLine( ( result != int.MaxValue ? result : -1 ) );
		}
		private static int Calculate( int orderCount )
		{
			// 現時点での最短手を超過している場合はそれ以上計算しても無駄
			var pos = (int)_stack.Pop();
			if( orderCount > _nowBestOrderCount )
				return int.MaxValue;
			// 前方向と後方向への移動をそれぞれ計算する
			// ※前→後ろの順でチェックする
			if( pos == _n )
				return orderCount;
			// 移動先が範囲外だったり、前回来た時よりも手数を上回っている場合は処理しない
			// この時点で手数が上回っている場合はどうやっても巻き返せない
			var calcCount = 0;
			var backward = pos - (int)_bitCountTable[pos];
			if( ( backward > 0 && (int)_history[backward] > orderCount + 1 ) )
			{
				_stack.Push( backward );
				_history[backward] = orderCount + 1;
				calcCount ++;
			}
			var forward = pos + (int)_bitCountTable[pos];
			if( forward <= _n && ( (int)_history[forward] > orderCount + 1 ) )
			{
				_stack.Push( forward );
				_history[forward] = orderCount + 1;
				calcCount++;
			}
			var result = int.MaxValue;
			for( var i = 0; i < calcCount; i++ )
			{
				var calculatedCount = Calculate( orderCount + 1 );
				if( result > calculatedCount )
					result = calculatedCount;
				if( _nowBestOrderCount > result )
					_nowBestOrderCount = result;
			}
			return result;
		}
	}
}
            
            
            
        