PackingProblemData figureFragmentation(Figure figure)
{
    PackingProblemData res;
    Figure frag;
    Figure resFragmentation;
    Figure maxFragmentation;
    Quantum q;

    for (int i = 0; i < figure.count(); ++i)
    {
        if (figure[i] == sep)
        {
            ListXY xy = gridNodes(frag);
            q = quantumFragmentation(xy, frag);

            //----<Figures output>----
            ListDouble x = xy.first;
            ListDouble y = xy.second;
            bool **grid = q.second;
            for (int j = 0; j < y.count() - 1; ++j)
            {
                for (int i = 0; i < x.count() - 1; ++i)
                {
                    if (grid[i][j])
                    {
                        cout << "+";
                    }
                    else
                    {
                        cout << " ";
                    }
                }
                cout << "\n";
            }
            cout << "\n---------------\n";
            //----<END output>----

            resFragmentation.append(q.first);
            maxFragmentation.append(maxFigure(Field(xy, q.second)));
            frag.clear();
        }
        else
        {
            frag.append(figure[i]);
        }
    }
    res.append(figure);
    res.append(resFragmentation);
    res.append(maxFragmentation);
    cout << "Quantum fragmentation count " << resFragmentation.count() << "\n";
    return res;
}
Quantum quantumFragmentation(ListXY xy, Figure f)
{
    ListDouble x = xy.first;
    ListDouble y = xy.second;
    double w, h;
    Figure res;
    RectByLines rectSource, rectGrid;
    bool **square = new bool* [x.count() - 1];
    for (int i = 0; i < x.count() - 1; ++i)
    {
        square[i] = new bool [y.count() - 1];
        memset(square[i], false, sizeof(bool) * (y.count() - 1));
        for (int j = 0; j < y.count() - 1; ++j)
        {
            w = x[i + 1] - x[i];
            h = y[j + 1] - y[j];
            for (int k = 0; k < f.count(); ++k)
            {
                rectSource = fromQRect(f[k]);
                rectGrid = RectByLines(x[i], x[i + 1], y[j], y[j + 1]);
                if (isInclude(rectSource, rectGrid))
                {
                    res.append(fromLines(rectGrid));
                    square[i][j] = true;
                    break;
                }
            }
        }
    }
    return Quantum(res, square);
}
Figure readFile(char *filename)
{
    freopen(filename, "r", stdin);
    int num;
    cin >> num;
    double k, x, y, w, h;
    Figure f;
    for (int i = 0; i < num; ++i)
    {
        cin >> k;
        for (int j = 0; j < k; ++j)
        {
            cin >> x >> y >> w >> h;
            f.append(QRectF(x, y, w, h));
        }
        f.append(sep);
    }
    return f;
}
Figure maxFigure(Field q)
{
    Figure res;
    ListXY xy = q.first;
    bool **grid = q.second;
    ListDouble x = xy.first;
    ListDouble y = xy.second;

    int xSqrCnt = x.count() - 1;
    int ySqrCnt = y.count() - 1;
    typedef QPair<QPoint, QPoint> VertexPairs;
    typedef QList<VertexPairs> Squares;
    Squares sq;
    int l, t, r, b;

    // Выбор всех прямоугольников
    for (l = 0; l < xSqrCnt; ++l)
    {
        for (t = 0; t < ySqrCnt; ++t)
        {
            for (r = xSqrCnt; r > l; --r)
            {
                for (b = ySqrCnt; b > t; --b)
                {
                    if (grid[l][t])
                    {
                        sq.append(VertexPairs(QPoint(l, t), QPoint(r, b)));
                    }
                }
            }
        }
    }

    QPoint lt, rb;
    bool isAdding;
    int **gridSep = new int* [xSqrCnt];
    for (int i = 0; i < xSqrCnt; ++i)
    {
        gridSep[i] = new int [ySqrCnt];
        memset(gridSep[i], 0, sizeof(int) * ySqrCnt);
    }

    int iter = 1;
    Squares inFigure;

    // сортировка по площади
    double s1, s2;
    for (int i = 0; i < sq.count(); ++i)
    {
        for (int j = i + 1; j < sq.count(); ++j)
        {
            lt = sq[i].first;
            rb = sq[i].second;
            l = lt.x();
            t = lt.y();
            r = rb.x();
            b = rb.y();
            s1 = (x[r] - x[l]) * (y[b] - y[t]);

            lt = sq[j].first;
            rb = sq[j].second;
            l = lt.x();
            t = lt.y();
            r = rb.x();
            b = rb.y();
            s2 = (x[r] - x[l]) * (y[b] - y[t]);

            if (s1 < s2)
            {
                sq.swap(i, j);
            }
        }
    }

    // Выбор прямоугольников, принадлежащих фигуре и разбиение
    for (int k = 0; k < sq.count(); ++k)
    {
        lt = sq[k].first;
        rb = sq[k].second;
        l = lt.x();
        t = lt.y();
        r = rb.x();
        b = rb.y();

        isAdding = true;
        for (int i = l; i < r; ++i)
        {
            for (int j = t; j < b; ++j)
            {
                isAdding = isAdding && grid[i][j];
            }
        }

        if (isAdding)
        {
            inFigure.append(VertexPairs(QPoint(l, t), QPoint(r, b)));
            for (int i = l; i < r; ++i)
            {
                for (int j = t; j < b; ++j)
                {
                    grid[i][j] = false;
                    gridSep[i][j] = iter;
                }
            }
            ++iter;
            res.append(QRectF(x[l], y[t], x[r] - x[l], y[b] - y[t]));
        }
    }

//    //----<Figures output>----
//    for (int j = 0; j < ySqrCnt; ++j)
//    {
//        for (int i = 0; i < xSqrCnt; ++i)
//        {
//            if (gridSep[i][j])
//            {
//                cout << setw(2) << gridSep[i][j];
//            }
//            else
//            {
//                cout << "--";
//            }
//        }
//        cout << "\n";
//    }
//    cout << "\n---------------\n";
//    //----<END output>----

    for (int i = 0; i < x.count() - 1; ++i)
    {
        delete grid[i];
    }
    delete grid;
    return res;
}