【发布时间】:2020-12-29 19:29:09
【问题描述】:
问题:用不接触或不重叠的正方形(任何大小)填充网格,即使在角落也是如此。下面的数字和在 右表示填充的网格方块的数量 对应的列/行。
为了解决这个问题,我应用了以下约束:放置的正方形应该是不相交的,并且为了确保网格正方形的数量是正确的,我将与给定行/列相交的正方形的长度总和限制为等于该行/列数。
但是,输出的解是 [1, 0, 0, 1] ([NumSquares, X, Y, SquareSize],一个在坐标 (0, 0) 中长度值为 1 的正方形,它应该是如右图所示(13 个不同大小和坐标的正方形)。
:- use_module(library(clpfd)).
:- include('utils.pl').
solve(Rows, Columns, Vars) :-
% Domain and variables definition
length(Rows, Size),
MaxNumSquares is Size * Size,
NumSquares #>= 0,
NumSquares #< MaxNumSquares,
length(StartsX, NumSquares),
length(StartsY, NumSquares),
length(SquareSizes, NumSquares),
S is Size - 1,
domain(StartsX, 0, S),
domain(StartsY, 0, S),
domain(SquareSizes, 1, Size),
construct_squares(Size, StartsX, StartsY, SquareSizes, Squares),
% Constraints
disjoint2(Squares, [margin(0, 0, 1, 1)]),
lines_constraints(0, Rows, StartsX, SquareSizes),
lines_constraints(0, Columns, StartsY, SquareSizes),
% Solution search
VarsList = [NumSquares, StartsX, StartsY, SquareSizes],
flatten(VarsList, Vars),
labeling([], Vars).
construct_squares(_, [], [], [], []).
construct_squares(Size, [StartX|T1], [StartY|T2], [SquareSize|T3], [square(StartX, SquareSize, StartY, SquareSize)|T4]) :-
StartX + SquareSize #=< Size,
StartY + SquareSize #=< Size,
construct_squares(Size, T1, T2, T3, T4).
% Rows and columns NumFilledCells cells constraints
lines_constraints(_, [], _, _).
lines_constraints(Index, [NumFilledCells|T], Starts, SquareSizes) :-
line_constraints(Index, NumFilledCells, Starts, SquareSizes),
I is Index + 1,
lines_constraints(I, T, Starts, SquareSizes).
line_constraints(Index, NumFilledCells, Starts, SquareSizes) :-
findall(
SquareSize,
(
element(N, Starts, Start),
element(N, SquareSizes, SquareSize),
intersect(Index, Start, SquareSize)
),
Lines),
sum(Lines, #=, NumFilledCells).
% Check if a square intersects a row or column
intersect(Index, Start, SquareSize) :-
Start #=< Index,
Index #=< Start + SquareSize.
【问题讨论】:
标签: prolog clpfd sicstus-prolog