Добавь в PlacementAlgorithmTest проверку для пересечения элементов.
вот мои файлы:
1 файл:
    package plata;

    public class Board {
        private int width;
        private int height;

        public Board(int width, int height) {
            this.width = width;
            this.height = height;
        }

        // Геттеры
        public int getWidth() { return width; }
        public int getHeight() { return height; }
    }

2 файл:
package plata;

public class Component {
    private int id;
    private int width;
    private int height;
    private int x;
    private int y;
    private int orientation; // 0 - 0°, 1 - 90°, 2 - 180°, 3 - 270°

    public Component(int id, int width, int height) {
        this.id = id;
        this.width = width;
        this.height = height;
        this.x = 0;
        this.y = 0;
        this.orientation = 0;
    }

    // Геттеры и сеттеры
    public int getId() { return id; }
    public int getWidth() { return width; }
    public int getHeight() { return height; }
    public int getX() { return x; }
    public int getY() { return y; }
    public int getOrientation() { return orientation; }
    public void setX(int x) { this.x = x; }
    public void setY(int y) { this.y = y; }
    public void setOrientation(int orientation) { this.orientation = orientation; }
}

3 файл:
package plata;

import java.util.ArrayList;
import java.util.List;
public class Placement {
    private List<Component> components;

    public Placement() {
        this.components = new ArrayList<>();
    }

    public void addComponent(Component component) {
        components.add(component);
    }

    public List<Component> getComponents() {
        return components;
    }
}

4 файл:
package plata;

import java.util.List;
import java.util.Random;

public class PlacementAlgorithm {
    private static final double INITIAL_TEMPERATURE = 1000.0;
    private static final double COOLING_RATE = 0.95;
    private static final double MIN_TEMPERATURE = 0.01;
    private static final int NUM_ITERATIONS = 1000;

    private static Random random = new Random();

    public static Placement findOptimalPlacement(List<Component> components, Board board) {
        double temperature = INITIAL_TEMPERATURE;
        Placement currentPlacement = generateInitialPlacement(components, board);
        Placement bestPlacement = currentPlacement;

        while (temperature > MIN_TEMPERATURE) {
            for (int i = 0; i < NUM_ITERATIONS; i++) {
                Placement newPlacement = generateNeighborPlacement(currentPlacement, board);
                double deltaCost = calculateCost(newPlacement, board) - calculateCost(currentPlacement, board);
                if (deltaCost < 0 || Math.exp(-deltaCost / temperature) > Math.random()) {
                    currentPlacement = newPlacement;
                    if (calculateCost(currentPlacement, board) < calculateCost(bestPlacement, board)) {
                        bestPlacement = currentPlacement;
                    }
                }
            }
            temperature *= COOLING_RATE;
        }
        printBoard(bestPlacement, board);
        return bestPlacement;
    }

    public static void printBoard(Placement placement, Board board) {
        char[][] boardArray = new char[board.getHeight()][board.getWidth()];

        // Заполняем доску точками, представляющими пустые пространства
        for (int i = 0; i < board.getHeight(); i++) {
            for (int j = 0; j < board.getWidth(); j++) {
                boardArray[i][j] = '.';
            }
        }

        for (Component component : placement.getComponents()) {
            char componentChar = (char) ('A' + component.getId()); // Обозначаем компонент буквой

            for (int i = 0; i < component.getHeight(); i++) {
                for (int j = 0; j < component.getWidth(); j++) {
                    int x = component.getX() + j;
                    int y = component.getY() + i;
                    if (x < board.getWidth() && y < board.getHeight()) {
                        boardArray[y][x] = componentChar;
                    }
                }
            }
        }

        // Печатаем доску
        System.out.println("Current Board Layout:");
        for (int i = 0; i < board.getHeight(); i++) {
            for (int j = 0; j < board.getWidth(); j++) {
                System.out.print(boardArray[i][j] + " ");
            }
            System.out.println();
        }
    }

    public static Placement generateInitialPlacement(List<Component> components, Board board) {
        Placement placement = new Placement();
        for (Component component : components) {
            // Размещаем компоненты в пределах доски случайным образом
            int x = random.nextInt(board.getWidth() - component.getWidth() + 1);
            int y = random.nextInt(board.getHeight() - component.getHeight() + 1);
            component.setX(x);
            component.setY(y);
            placement.addComponent(component);
        }
        return placement;
    }

    public static Placement generateNeighborPlacement(Placement currentPlacement, Board board) {
        Placement newPlacement = new Placement();
        List<Component> components = currentPlacement.getComponents();

        for (Component component : components) {
            Component newComponent = new Component(component.getId(), component.getWidth(), component.getHeight());

            // Случайная трансформация позиции или ориентации
            if (random.nextBoolean()) {
                int x = random.nextInt(board.getWidth() - component.getWidth() + 1);
                int y = random.nextInt(board.getHeight() - component.getHeight() + 1);
                newComponent.setX(x);
                newComponent.setY(y);
            } else {
                int orientation = random.nextInt(4);
                newComponent.setOrientation(orientation);
            }
            newPlacement.addComponent(newComponent);
        }

        return newPlacement;
    }

    public static double calculateCost(Placement placement, Board board) {
        double cost = 0.0;

        // Список с координатами, которые уже заняты компонентами
        boolean[][] occupied = new boolean[board.getHeight()][board.getWidth()];

        for (Component component : placement.getComponents()) {
            // Проверка на выход за пределы доски
            if (component.getX() + component.getWidth() > board.getWidth() ||
                    component.getY() + component.getHeight() > board.getHeight()) {
                cost += 1000; // Штраф за выход за пределы
            }

            // Проверка пересечения компонентов
            for (int i = 0; i < component.getHeight(); i++) {
                for (int j = 0; j < component.getWidth(); j++) {
                    int x = component.getX() + j;
                    int y = component.getY() + i;
                    if (x < board.getWidth() && y < board.getHeight()) {
                        if (occupied[y][x]) {
                            cost += 500; // Штраф за пересечение
                        } else {
                            occupied[y][x] = true; // Отметить, что эта клетка теперь занята
                        }
                    }
                }
            }
        }

        // Добавление оценки расстояний между компонентами
        List<Component> components = placement.getComponents();
        for (int i = 0; i < components.size(); i++) {
            for (int j = i + 1; j < components.size(); j++) {
                Component comp1 = components.get(i);
                Component comp2 = components.get(j);

                double centerX1 = comp1.getX() + comp1.getWidth() / 2.0;
                double centerY1 = comp1.getY() + comp1.getHeight() / 2.0;
                double centerX2 = comp2.getX() + comp2.getWidth() / 2.0;
                double centerY2 = comp2.getY() + comp2.getHeight() / 2.0;

                double distance = Math.sqrt(Math.pow(centerX1 - centerX2, 2) + Math.pow(centerY1 - centerY2, 2));
                cost += distance;
            }
        }

        return cost;
    }
}

5 файл:
package plata;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Arrays;
import java.util.List;

public class PlacementAlgorithmTest {

    @Test
    public void testFindOptimalPlacement() {
        Board board = new Board(10, 10);
        List<Component> components = Arrays.asList(
                new Component(0, 3, 1),
                new Component(1, 2, 4),
                new Component(2, 3, 3),
                new Component(3, 5, 2)
        );

        Placement optimalPlacement = PlacementAlgorithm.findOptimalPlacement(components, board);

        // Проверка, что все компоненты расположены в пределах доски
        for (Component component : optimalPlacement.getComponents()) {
            assertTrue(component.getX() >= 0, "X position is outside the board");
            assertTrue(component.getY() >= 0, "Y position is outside the board");
            assertTrue(component.getX() + component.getWidth() <= board.getWidth(), "Component exceeds board width");
            assertTrue(component.getY() + component.getHeight() <= board.getHeight(), "Component exceeds board height");
        }
    }
}