动态编程 - 确定状态

时间:2012-06-30 09:55:30

标签: algorithm dynamic state dynamic-programming

我最近在动态编程课程中遇到过这个问题,老实说,我不知道如何确定合适的状态。

您给出 N (1 <= N <= 70)段落和 M (1 <= M <= N)个数字。每个段落 i 需要 PL_i (1&lt; = PL_i&lt; = 100)行并且最多引用一个数字。每个图只引用一次(即,没有两个段落可以引用相同的图,并且对于每个图都有一个引用它的段落。)每个图需要 PF_i (1 <= PF_i <= 100)行。

任务是按照给出的顺序在纸上分发这些数字和段落,其中一篇论文最多适合 L 行。没有任何段落或数字太大,无法放在一张纸上。如果 x 上的段落 x 引用数字 y ,那么 y 必须放在纸张< strong> x_p - 1 或 x_p x_p + 1

我们必须找到要分配的最小行数(以及页面),以便分发所有数字和段落。任何帮助将非常感激。提前谢谢!

4 个答案:

答案 0 :(得分:1)

作为当前页面P的DP状态,您可以使用一个数组(大小 L * 2),使用行数索引,在页面P上保留数字,从第P +页引用从页面P开始,在页面P + 1上需要1或(否定)行数。

每个数组元素由两个值组成:

  1. x - 分页数,分布在第1页...... P;
  2. DP算法完成后恢复段落/数字分布所需的一些数据。
  3. 使用此数组计算下一页的数组(P + 1)。对于数组P的每个有效元素,将新段落( x +1, x +2,...)添加到页面P + 1,更新对应的元素数组P + 1。尽管有可能,请将这些段落引用的数字放在页面P上,然后放在页面P + 1上,然后放在页面P + 2上。覆盖数组P + 1的元素,具有较低的 x 值,具有较高的值。

    此算法的时间复杂度为O( L * N ):每页行数乘以段落数。因为处理每个页面是O(每页行数*平均页数每页)。

答案 1 :(得分:1)

一般存在问题,你必须重新排序paragraps P和Figure P ether(P,F)顺序或(F,P)顺序。

放置在文档中的是(P1,F1),(P2,F2),(P3,F3),其中每个元组(P,F)可以是任何顺序(P,F)或(F,P)并且那里是一些长度为0的Fs,意味着没有F。

问题是找到每个(P,F)对的排序。

找到最少数量的Paiges的一个解决方案是应用此规则

lines_total = MIN(lines(P,F),lines(F,P)) + remaining() //this is custom addition

好的,这个功能缺乏原型,但对于C来说就像

calc_spend_lines(pfpairs * pairs)

pfpaires在哪里

typedef struct
{
   int P;
   int F;
} pfpaires;

你知道,例如,当P为0时,你就达到了目的。

你所要做的就是制作功能,实现那个特殊的+符号,记住分页符和死线。

这给出了O(N)解决方案,因为你的结束条件是0,所以最小页数而不是行数。

如果你想最小化线数,你可以使用二分法将结束条件设置为别的而不是0,这样就可以了

O(N * log(L))解决方案

修改
由于在当前P和F之间可以存在其他P,因此只需要检查而不是((F,P),(P,F))也检查空白页(N),因此组合是((P,F)( P,N,F),(F,P),(F,N,P))。 结论是,你最终会得到更复杂的算法,但是复杂度相同。点是,一旦你检查了4个排序中的一个,只有一种简单的方法可以做出最佳定位,只有当前的状态(行)有点复杂。

答案 2 :(得分:1)

可以优化,但它的工作解决方案:

public class ParagraphsAndFigures {

        public static ArrayList<PageContent> generatePages(List<Paragraph> paragraphs, int L) {
            ArrayList<PageContent> pages = new ArrayList<PageContent>();
            for (int i = 0; i < paragraphs.size() * 2; i++) {
                pages.add(new PageContent());
            }
            int page = 0;

            for (Paragraph paragraph : paragraphs) {
                do {
                    int cur = pages.get(page).linesReserved;
                    int next = pages.get(page + 1).linesReserved;

                    if (cur + paragraph.size < L) {
                        cur += paragraph.size;

                        if (paragraph.figure != null) {

                            if (pages.get(page + 1).hasPicture()) {
                                if (next + paragraph.figure.size < L) {
                                    pages.get(page).texts.add(paragraph);
                                    pages.get(page + 1).texts.add(paragraph.figure);
                                    pages.get(page).linesReserved += paragraph.size;
                                    pages.get(page + 1).linesReserved += paragraph.figure.size;
                                    break; // next paragraph
                                } else {
                                    page++;
                                    continue;
                                }
                            }

                            if (pages.get(page).hasPicture()) {
                                if (cur + paragraph.figure.size < L) {
                                    pages.get(page).texts.add(paragraph);
                                    pages.get(page).texts.add(paragraph.figure);
                                    pages.get(page).linesReserved += paragraph.size;
                                    pages.get(page).linesReserved += paragraph.figure.size;
                                    break; // next paragraph
                                } else {
                                    if (next + paragraph.figure.size < L) {
                                        pages.get(page).texts.add(paragraph);
                                        pages.get(page + 1).texts.add(paragraph.figure);
                                        pages.get(page).linesReserved += paragraph.size;
                                        pages.get(page + 1).linesReserved += paragraph.figure.size;
                                        break; // next paragraph
                                    }
                                    page++;
                                    continue;
                                }
                            }

                            if (page != 0 && pages.get(page - 1).hasPicture()) {
                                int prev = pages.get(page - 1).linesReserved;
                                if (prev + paragraph.figure.size < L) {
                                    pages.get(page).texts.add(paragraph);
                                    pages.get(page - 1).texts.add(paragraph.figure);
                                    pages.get(page).linesReserved += paragraph.size;
                                    pages.get(page - 1).linesReserved += paragraph.figure.size;
                                    break; // next paragraph
                                } else {
                                    if (cur + paragraph.figure.size < L) {
                                        pages.get(page).texts.add(paragraph);
                                        pages.get(page).texts.add(paragraph.figure);
                                        pages.get(page).linesReserved += paragraph.size;
                                        pages.get(page).linesReserved += paragraph.figure.size;
                                        break; // next paragraph
                                    }
                                    if (next + paragraph.figure.size < L) {
                                        pages.get(page).texts.add(paragraph);
                                        pages.get(page + 1).texts.add(paragraph.figure);
                                        pages.get(page).linesReserved += paragraph.size;
                                        pages.get(page + 1).linesReserved += paragraph.figure.size;
                                        break; // next paragraph
                                    }
                                    page++;
                                }
                            }

                            if (page != 0) {
                                int prev = pages.get(page - 1).linesReserved;
                                if ( prev + paragraph.figure.size < L) {
                                    pages.get(page).texts.add(paragraph);
                                    pages.get(page - 1).texts.add(paragraph.figure);
                                    pages.get(page).linesReserved += paragraph.size;
                                    pages.get(page - 1).linesReserved += paragraph.figure.size;
                                    break; // next paragraph
                                }
                            }

                            if (cur + paragraph.figure.size < L) {
                                pages.get(page).texts.add(paragraph);
                                pages.get(page).texts.add(paragraph.figure);
                                pages.get(page).linesReserved += paragraph.size;
                                pages.get(page).linesReserved += paragraph.figure.size;
                                break; // next paragraph
                            }

                            if (next + paragraph.figure.size < L) {
                                pages.get(page).texts.add(paragraph);
                                pages.get(page + 1).texts.add(paragraph.figure);
                                pages.get(page).linesReserved += paragraph.size;
                                pages.get(page + 1).linesReserved += paragraph.figure.size;
                                break; // next paragraph
                            }
                            page++;
                        }
                    }
                    page++;
                } while (true);
            }
            return pages;
        }
    }

And tests:

public class ParagraphsAndFiguresTest {
            @Test
            public void pageGeneration1() throws Exception {
                // given
                ArrayList paragraphs = new ArrayList();
                paragraphs.add(new Paragraph(20,21));
                paragraphs.add(new Paragraph(22,23));
                paragraphs.add(new Paragraph(24,25));

// when ArrayList<PageContent> pageContents = ParagraphsAndFigures.generatePages(paragraphs, 50); // then assertThat(transformToList(pageContents), is(asList("20", "21", "p0" ,"22" ,"23", "p1" ,"24" ,"25", "p2"))); } @Test public void pageGeneration2() throws Exception { // given ArrayList<Paragraph> paragraphs = new ArrayList<Paragraph>(); paragraphs.add(new Paragraph(10,11)); paragraphs.add(new Paragraph(28,21)); paragraphs.add(new Paragraph(22,23)); // when ArrayList<PageContent> pageContents = ParagraphsAndFigures.generatePages(paragraphs, 50); // then assertThat(transformToList(pageContents), is(asList("10", "11" ,"28", "p0" ,"21", "22" , "p1" ,"23", "p2"))); } @Test public void pageGeneration3() throws Exception { // given ArrayList<Paragraph> paragraphs = new ArrayList<Paragraph>(); paragraphs.add(new Paragraph(10,11)); paragraphs.add(new Paragraph(12,30)); paragraphs.add(new Paragraph(13,19)); // when ArrayList<PageContent> pageContents = ParagraphsAndFigures.generatePages(paragraphs, 50); // then assertThat(transformToList(pageContents), is(asList("10", "11" ,"12", "13", "p0" ,"30", "19" , "p1" ))); } @Test public void pageGeneration4() throws Exception { // given ArrayList<Paragraph> paragraphs = new ArrayList<Paragraph>(); paragraphs.add(new Paragraph(10,11)); paragraphs.add(new Paragraph(30,12)); paragraphs.add(new Paragraph(13,16)); // when ArrayList<PageContent> pageContents = ParagraphsAndFigures.generatePages(paragraphs, 50); // then assertThat(transformToList(pageContents), is(asList("10", "11" ,"12", "16", "p0" ,"30", "13" ,"p1" ))); } @Test public void pageGeneration5() throws Exception { // given ArrayList<Paragraph> paragraphs = new ArrayList<Paragraph>(); paragraphs.add(new Paragraph(31,32)); paragraphs.add(new Paragraph(17,21)); paragraphs.add(new Paragraph(30,35)); // when ArrayList<PageContent> pageContents = ParagraphsAndFigures.generatePages(paragraphs, 50); // then assertThat(transformToList(pageContents), is(asList("31", "p0", "32", "17", "p1", "21", "p2", "30", "p3", "35", "p4"))); } private List<String> transformToList(ArrayList<PageContent> pageContents) { List<String> result = new ArrayList<String>(); for (int i = 0; i < pageContents.size(); i++) { PageContent pageContent = pageContents.get(i); if (!pageContent.texts.isEmpty()) { for (Text text : pageContent.texts) { result.add(String.valueOf(text.size)); } result.add("p"+i); } } return result; } }
// when ArrayList<PageContent> pageContents = ParagraphsAndFigures.generatePages(paragraphs, 50); // then assertThat(transformToList(pageContents), is(asList("20", "21", "p0" ,"22" ,"23", "p1" ,"24" ,"25", "p2"))); } @Test public void pageGeneration2() throws Exception { // given ArrayList<Paragraph> paragraphs = new ArrayList<Paragraph>(); paragraphs.add(new Paragraph(10,11)); paragraphs.add(new Paragraph(28,21)); paragraphs.add(new Paragraph(22,23)); // when ArrayList<PageContent> pageContents = ParagraphsAndFigures.generatePages(paragraphs, 50); // then assertThat(transformToList(pageContents), is(asList("10", "11" ,"28", "p0" ,"21", "22" , "p1" ,"23", "p2"))); } @Test public void pageGeneration3() throws Exception { // given ArrayList<Paragraph> paragraphs = new ArrayList<Paragraph>(); paragraphs.add(new Paragraph(10,11)); paragraphs.add(new Paragraph(12,30)); paragraphs.add(new Paragraph(13,19)); // when ArrayList<PageContent> pageContents = ParagraphsAndFigures.generatePages(paragraphs, 50); // then assertThat(transformToList(pageContents), is(asList("10", "11" ,"12", "13", "p0" ,"30", "19" , "p1" ))); } @Test public void pageGeneration4() throws Exception { // given ArrayList<Paragraph> paragraphs = new ArrayList<Paragraph>(); paragraphs.add(new Paragraph(10,11)); paragraphs.add(new Paragraph(30,12)); paragraphs.add(new Paragraph(13,16)); // when ArrayList<PageContent> pageContents = ParagraphsAndFigures.generatePages(paragraphs, 50); // then assertThat(transformToList(pageContents), is(asList("10", "11" ,"12", "16", "p0" ,"30", "13" ,"p1" ))); } @Test public void pageGeneration5() throws Exception { // given ArrayList<Paragraph> paragraphs = new ArrayList<Paragraph>(); paragraphs.add(new Paragraph(31,32)); paragraphs.add(new Paragraph(17,21)); paragraphs.add(new Paragraph(30,35)); // when ArrayList<PageContent> pageContents = ParagraphsAndFigures.generatePages(paragraphs, 50); // then assertThat(transformToList(pageContents), is(asList("31", "p0", "32", "17", "p1", "21", "p2", "30", "p3", "35", "p4"))); } private List<String> transformToList(ArrayList<PageContent> pageContents) { List<String> result = new ArrayList<String>(); for (int i = 0; i < pageContents.size(); i++) { PageContent pageContent = pageContents.get(i); if (!pageContent.texts.isEmpty()) { for (Text text : pageContent.texts) { result.add(String.valueOf(text.size)); } result.add("p"+i); } } return result; } }

答案 3 :(得分:-1)

起初我建议建立递归方法。

从变体中选择最佳:从段落或图形开始。

在每个步骤中,从可能的变体中选择最佳:添加分页,添加下一个数字,添加下一个段落。简单状态机将有助于消除禁止的变体(例如,行中的2个分页符),但这不是必需的。

当检查递归解决方案时,您可以将其转换为自上而下或自下而上的动态编程,如大多数关于DP的算法课程所述。