問題
定義
- 各要素を一度しか使用しない要素からこの数体系で自然数を書き込むことができる場合、自然数
N
を数体系の数集合の書き込み可能数(WN) と定義しましょう。「書かれた」のより厳密な定義: - ここでは連結を意味します。M
U
CONCAT
- 自然数が andの WN 数であり、andの CAN数である場合、自然数を数値システムの記号セットの連続到達可能数
N
(CAN)として定義しましょう(別の定義は、すべての数がおよび)の WN 。より厳密:M
U
M
N-1
U
M
N
U
M
0 .. N
U
M
問題
自然数の集合があるとしましょうS
: (ゼロを自然数として扱っています) と自然数
M
, M>1
. U
問題は、与えられたとの最大 CAN (MCAN) を見つけることM
です。指定されたセットU
には重複が含まれる可能性がありますが、各重複は複数回使用できませんでした (つまり、U
{x, y, y, z} が含まれている場合、それぞれy
が 0 回または 1 回y
使用される可能性があるため、0..合計2回)。数値システムでもU
有効であることが期待されます(つまりM
、シンボルを含むことはできず、if のいずれのメンバーにも含めることはできません)。そして、当然のことながら、 のメンバーは数値であり、記号ではありません(したがって、8
9
M=8
U
M
11
M=10
) - そうでなければ、問題は簡単です。
私のアプローチ
現在の番号がCANであるかどうかを単純にチェックする単純なアルゴリズムを考えています。
0
WN が指定されているU
かM
どうかを確認します。2 に進む: これで完了です。MCAN は null です1
WN が指定されているU
かM
どうかを確認します。3 に進む: これで完了です。MCAN は次のとおりです。0
- ...
したがって、このアルゴリズムはこのすべてのシーケンスを構築しようとしています。この部分は改善できないと思いますが、できるのでしょうか?ここで、number が WN かどうかを確認する方法を説明します。これはある種の「総当たり攻撃」でもあります。私はPHP関数でM=10
(実際、文字列を扱っているので、他のものは問題ではありません)それを認識しています:M
//$mNumber is our N, $rgNumbers is our U
function isWriteable($mNumber, $rgNumbers)
{
if(in_array((string)$mNumber, $rgNumbers=array_map('strval', $rgNumbers), true))
{
return true;
}
for($i=1; $i<=strlen((string)$mNumber); $i++)
{
foreach($rgKeys = array_keys(array_filter($rgNumbers, function($sX) use ($mNumber, $i)
{
return $sX==substr((string)$mNumber, 0, $i);
})) as $iKey)
{
$rgTemp = $rgNumbers;
unset($rgTemp[$iKey]);
if(isWriteable(substr((string)$mNumber, $i), $rgTemp))
{
return true;
}
}
}
return false;
}
-つまり、一部を試してから、残りの部分が再帰で記述できるかどうかを確認します。書き込めない場合は、 の次のメンバーを試していますU
。ここは改善点だと思います。
仕様
ご覧のとおり、アルゴリズムは前にすべての数値を構築しN
、それらが WN であるかどうかを確認しようとしています。しかし、唯一の問題は、MCAN を見つけることです。つまり、問題は次のとおりです。
- ここでは建設的なアルゴリズムが過剰である可能性がありますか? はいの場合、他にどのようなオプションを使用できますか?
U
number が指定されたandの WN であるかどうかを判断するより迅速な方法はありM
ますか? (前のポイントに肯定的な答えがある場合、このポイントは意味をなさない可能性があり、前にすべての数値を構築してチェックするわけではありませんN
)。
サンプル
U = {4, 1, 5, 2, 0} M = 10
次に、MCAN = 2 (3 に到達できませんでした)
U = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11} M = 10
次に、MCAN = 21 (合計で 2 つのシンボル22
がないため、以前のすべてに到達できます)。2