Created
June 27, 2015 15:30
-
-
Save outlandkarasu/b73a7766d3d8c8f32478 to your computer and use it in GitHub Desktop.
NP完全問題の1つである部分和問題を腕ずくで解くプログラム
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import std.stdio; | |
import std.algorithm; | |
import std.conv; | |
import std.array; | |
import std.c.stdlib; | |
/// 数列の最大要素数 | |
immutable MAX_NUMS = size_t.sizeof * 8; | |
/** | |
* メイン関数 | |
* | |
* Params: | |
* args = コマンドライン引数。数列と部分和になるか判定する数を指定する。 | |
*/ | |
void main(string[] args) { | |
// コマンドライン引数から入力を得る | |
auto input = map!(to!int)(args[1 .. $]); | |
if(input.length < 2) { | |
// 引数少なすぎ | |
stderr.writeln("too few arguments."); | |
exit(-1); | |
return; | |
} else if(input.length > MAX_NUMS + 1) { | |
// 引数多すぎ | |
stderr.writeln("too many arguments."); | |
exit(-1); | |
return; | |
} | |
// 数列と判定対象の値に分ける | |
immutable nums = array(input[0 .. $ - 1]); | |
immutable n = input[$ - 1]; | |
writefln("nums: %s", nums); | |
writefln("n: %s", n); | |
// 数列の全組み合わせについて処理する | |
foreach(flags; 1 .. (1UL << nums.length)) { | |
// フラグの立っている数の合計を出す | |
int sum = 0; | |
eachFlaggedNumber!(v => sum += v)(flags, nums); | |
// 合計値がnであれば答えとして出力する | |
if(sum == n) { | |
int[] answer; | |
eachFlaggedNumber!(v => answer ~= v)(flags, nums); | |
writefln("answer: %s", answer); | |
} | |
} | |
} | |
/// 数列のうちフラグの立っている値をfで処理する | |
void eachFlaggedNumber(alias f)(size_t flags, const(int)[] nums) { | |
foreach(i, n; nums) { | |
if((flags & (1UL << i)) != 0) { | |
f(n); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
使用方法
コマンドライン引数に数列と判定対象の値を指定する。(最後の数字が判定対象の値)
出力結果
数列がnums、判定対象の値がn、nになる数の組み合わせがanswerとして出力される。
解が複数あればその分answerが出てくる。解なしの場合は出てこない。