【问题标题】:Dynamic programming - determining the state动态规划 - 确定状态
【发布时间】:2012-07-01 15:47:11
【问题描述】:

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

您有 N (1 M (1 i 需要 PL_i (1 PF_i (1

任务是按照给定的顺序将这些图形和段落分布在纸上,其中一张纸最多适合 L 行。没有段落或图形太大而不能放在一张纸上。如果放置在纸 x_p 上的段落 x 引用了图 y,则必须将 y 放置在纸上 y strong>x_p - 1 或 x_px_p + 1

为了分配所有的图表和段落,我们必须找到要分配的最少行数(以及相应的页数)。任何帮助将不胜感激。提前致谢!

【问题讨论】:

  • “按照给定的顺序”的含义至关重要。是否可以接受 2 个段落出现在一个页面上,而它们的引用数字都出现在下一页(或上一页)上?如果不是(即如果每个图都必须紧跟在相应段落之前或之后),那么问题就简单了。
  • @j_random_hacker 不,不一定。 “按给出的顺序”意味着您不能有两个段落 ab 使得 b 出现在 之前a 在输入中,但在最终分布中分配在 a 之后的论文中。
  • 您是说我的“是否可以接受...”问题的答案是“是”? (我知道paragraphs的输出顺序必须与段落的输入顺序相匹配,但我不清楚数字是否也是如此。)
  • @j_random_hacker 是的,答案是肯定的 :) 至于顺序,它适用于段落和数字。
  • 是否可以在多个页面上拆分一个段落?

标签: algorithm dynamic state dynamic-programming


【解决方案1】:

首先我建议构建递归方法。

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

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

当检查递归解决方案时,您可以将其转换为自顶向下或自底向上的动态规划,如大多数有关 DP 的算法课程中所述。

【讨论】:

  • 感谢您的回答!我认为主要问题是如何跟踪您“到目前为止所做的事情”——在递归方法中,您可以保留分配的段落和图形的整个数组,但在 DP 解决方案中,您不能这样做;在计算较大州的答案时,必须有一个技巧可以知道您需要分析什么。有什么想法吗?
  • 制作包含一些行的二维表 - 段落/状态,并从左到右填充。当您到达最后一列时,您将获得通过表格的最佳路线。
【解决方案2】:

作为当前页面 P 的 DP 状态,您可以使用一个数组(大小为 L * 2),按行数索引,在页面 P 上保留用于图形,从页面 P+ 引用1 行或(取反)行数,需要在第 P+1 页上获取图形,从第 P 页引用。

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

  1. x - 段落数,分布在第 1 .. P 页上;
  2. 一些数据,需要在 DP 算法完成后恢复段落/图形分布。

使用此数组计算下一页 (P+1) 的数组。对于数组 P 的每个有效元素,将新段落 (x+1, x+2, ...) 添加到页面 P+1,更新对应的元素数组 P+1。尽管可以,将这些段落引用的图形放在 P 页,然后放在 P+1 页,然后放在 P+2 页。用较高的值覆盖数组 P+1 中 x 值较低的元素。

该算法的时间复杂度为 O(L * N):每页行数乘以段落数。因为处理每一页是 O(lines-per-page * average-paragraphs-per-page)。

【讨论】:

    【解决方案3】:

    一般问题是您必须重新排序段落 P 和图形 P 以太 (P,F) 顺序或 (F,P) 顺序。

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

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

    找到最少 Paige 数的一种解决方案是应用此规则

    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 个排序中的一个,只有一种微不足道的方法可以做出最佳定位,只是当前状态(行)有点复杂。

    【讨论】:

    • 如果我正确理解了这个问题(见 cmets),可以放置一个图,以便在图和引用它的段落之间有其他段落(可能引用其他图),所以你需要更多不仅仅是直接的 (P, F) 配对
    • 非常感谢拉鲁!非常详尽的解释和解决方案。
    • 我会在 6 分钟内奖励你。再次感谢:)
    • @ralu: 声明 -“放置在文档中的是 (P1,F1),(P2,F2),(P3,F3) 其中每个元组 (P,F) 可以是任意顺序 (P ,F) 或 (F,P) 并且有些 Fs 的长度为 0,这意味着没有 F。”不对,因为可能会出现 (P1,P2),(F1,F2),(P3,F3) 和 (P1,F1,F3),(P2,P3),(F2) 之类的情况,所以找到两者之间的最小值(P,F) 和 (F,P) 不起作用。另外,由于您正在计算总行数,因此您的解决方案不会找到最少的页数,但有一个限制:P 不能放在 2 页上。
    【解决方案4】:

    可以优化,但它是有效的解决方案:

    公共类 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; } }

    和结构: 公共类 PageContent { int 行保留; 集合文本 = new ArrayList();

    公共布尔 hasPicture() { 对于(文本文本:文本){ if (text instanceof Figure) { 返回真; } } 返回假; } } 公共类文本{ 受保护的 int 大小; } 公共类图扩展文本{ } 公共类段落扩展文本{ 公共段落(int size,int fSIze){ this.size = 大小; this.figure = new Figure(); this.figure.size = fSIze; } 图图; }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-14
      • 2012-10-29
      相关资源
      最近更新 更多