我最近在动态编程课程中遇到过这个问题,老实说,我不知道如何确定合适的状态。
您给出 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 。
我们必须找到要分配的最小行数(以及页面),以便分发所有数字和段落。任何帮助将非常感激。提前谢谢!
答案 0 :(得分:1)
作为当前页面P的DP状态,您可以使用一个数组(大小 L * 2),使用行数索引,在页面P上保留数字,从第P +页引用从页面P开始,在页面P + 1上需要1或(否定)行数。
每个数组元素由两个值组成:
使用此数组计算下一页的数组(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的算法课程所述。