└このサイトは、Clingoエンジンを使って小さいグリッドの最適解を計算するためにアンサーセットプログラミングを利用してるよ。こういうグリッドを最大化するのはたぶんNP困難だね。伝統的なSATやSMTソルバーはフラッドフィルの計算がかなり非効率的だってことも覚えておいて。最適解を計算するために使っているASPの仕様は意外と短くて読みやすいよ。こんな感じ:#const budget=11. horse(4,4). cell(0,0). boundary(0,0). cell(0,1). boundary(0,1). % ...省略... cell(3,1). water(3,1). % ... % 隣接セル(4方向接続) adj(R,C, R+1,C) :- cell(R,C), cell(R+1,C). adj(R,C, R-1,C) :- cell(R,C), cell(R-1,C). adj(R,C, R,C+1) :- cell(R,C), cell(R,C+1). adj(R,C, R,C-1) :- cell(R,C), cell(R,C-1). % 歩ける = 水じゃない walkable(R,C) :- cell(R,C), not water(R,C). % 選択:馬とチェリー以外の歩けるセルに壁を置く { wall(R,C) } :- walkable(R,C), not horse(R,C), not cherry(R,C). % 予算制約(ネイティブカウント - ビットブラスティングなし!) :- #count { R,C : wall(R,C) } > budget. % 馬からの到達可能性(z = 囲まれた/到達可能なセル) z(R,C) :- horse(R,C). z(R2,C2) :- z(R1,C1), adj(R1,C1, R2,C2), walkable(R2,C2), not wall(R2,C2). % 馬は境界に到達できない(脱出するから) :- z(R,C), boundary(R,C). % 囲まれたエリアを最大化(チェリーは+3ボーナス = 合計4) #maximize { 4,R,C : z(R,C), cherry(R,C) ; 1,R,C : z(R,C), not cherry(R,C) }. % 壁の位置だけ出力 #show wall/2.