hiho一下第196周《图片排版》题目分析

12
0

《图片排版》题目分析

本题显而易见的做法是直接枚举删除了哪张图片,复杂度O(N);然后再通过O(N)的模拟排版计算出最后的高度。总的时间复杂度是O(N^2)。

优化的方法是用空间换时间,先预处理出一些有用的数据。

H(i):从头开始加入前i张图片后的情况,记录总高度、当前行高度、当前行剩余宽度。计算所有H(i)的复杂度是O(N)。

F(i, j): 假设当前行剩余宽度是j,这时开始加入第i张~最后一张的情况,记录增加的高度、当前行高度。计算所有F(i, j)的复杂度是O(NM)。

有了H(i)和F(i, j),我们再枚举删除的图片时,就可以直接合并相应的H和F,得到最终的高度。注意合并时,当前行高度需要取H和F两者中较大的。

总的复杂度是O(NM)。

1 answer(s)

0

大佬,麻烦看下问题出在哪,提交是50分,实在找不出原因,谢谢。

import java.io.File;
import java.io.PrintWriter;
import java.util.Scanner;

/**
 * This is the ACM problem solving program for hihoCoder 1365.
 * 
 * @version 2018-04-01
 */
public class Main {
    /**
     * record the picture size;
     */
    private static class Picture {
        int W, H;
    }

    /** For input. */
    private static Scanner scan;

    /** For output. */
    private static PrintWriter writer;

    /** Input data. */
    private static int M, N;

    /** Picture list */
    private static Picture[] pictures;

    /**
     * Used for D.P. The element dp1[i][0] means the height of article when
     * adding first i pictures, excluding the height of last line; dp1[i][1]
     * means the height of last line.
     */
    private static int[][] dp1;

    /**
     * Used for D.P. The element dp2[i][j][0] means the increased height given
     * the width available of the current line is j, then put number i ~ N
     * pictures, excluding the current line; while the dp2[i][j][1] means the
     * height of current line in this situation.
     */
    private static int[][][] dp2;

    /**
     * The main program.
     * 
     * @param args
     *            The command-line parameters list.
     */
    public static void main(String[] args) {
        initIO();

        input();
        computeDp1();
        computeDp2();
        computeResult();

        closeIO();
    }

    /**
     * Deal with input.
     */
    private static void input() {
        M = scan.nextInt();
        N = scan.nextInt();

        pictures = new Picture[N];

        for (int i = 0; i < N; i++) {
            pictures[i] = new Picture();
            pictures[i].W = scan.nextInt();
            pictures[i].H = scan.nextInt();
        }
    }

    /**
     * Compute the array dp1.
     */
    private static void computeDp1() {
        dp1 = new int[N][2];

        int lineWidth = M;
        int preHeight = 0;
        int currentHeight = 0;

        for (int i = 0; i < N; i++) {
            int h = -1;
            if (lineWidth >= pictures[i].W) {
                h = pictures[i].H;
                lineWidth -= pictures[i].W;
            } else {
                h = (int) Math.ceil((double) lineWidth / (double) pictures[i].W
                        * (double) pictures[i].H);
                lineWidth = 0;
            }

            if (h > currentHeight) {
                currentHeight = h;
            }

            dp1[i][0] = preHeight;
            dp1[i][1] = currentHeight;

            if (lineWidth == 0) {
                preHeight += currentHeight;
                currentHeight = 0;
                lineWidth = M;
            }
        }
    }

    /**
     * Compute the array dp2.
     */
    private static void computeDp2() {
        dp2 = new int[N][M + 1][2];

        for (int i = N - 1; i >= 0; i--) {
            for (int j = M; j > 0; j--) {
                int h = -1;
                if (pictures[i].W <= j) {
                    h = pictures[i].H;
                } else {
                    h = (int) Math.ceil((double) j / (double) pictures[i].W
                            * (double) pictures[i].H);
                }
                if (j - pictures[i].W > 0) {
                    if (i + 1 < N) {
                        dp2[i][j][0] = dp2[i + 1][j - pictures[i].W][0];
                        if (h > dp2[i + 1][j - pictures[i].W][1]) {
                            dp2[i][j][1] = h;
                        } else {
                            dp2[i][j][1] = dp2[i + 1][j - pictures[i].W][1];
                        }
                    } else {
                        dp2[i][j][0] = 0;
                        dp2[i][j][1] = h;
                    }
                } else {
                    if (i + 1 < N) {
                        dp2[i][j][0] = dp2[i + 1][M][0] + dp2[i + 1][M][1];
                    } else {
                        dp2[i][j][0] = 0;
                    }
                    dp2[i][j][1] = h;
                }
            }

        }
    }

    /**
     * Compute the result of this problem.
     */
    private static void computeResult() {
        if (N == 1) {
            writer.println("0");
            return;
        }
        int min = -1;
        int lineWidth = M;
        for (int i = 0; i < N; i++) {
            int r = -1;
            if (i == 0) {
                r = dp2[1][M][0] + dp2[1][M][1];
            } else if (i == N - 1) {
                r = dp1[N - 2][0] + dp1[N - 2][1];
            } else {
                r = dp1[i - 1][0] + dp2[i + 1][lineWidth][0];
                if (lineWidth == M) {
                    r += dp1[i - 1][1] + dp2[i + 1][lineWidth][1];
                } else {
                    r += dp1[i - 1][1] > dp2[i + 1][lineWidth][1]
                            ? dp1[i - 1][1] : dp2[i + 1][lineWidth][1];
                }
            }

            if (min == -1 || r < min) {
                min = r;
            }

            if (lineWidth > pictures[i].W) {
                lineWidth -= pictures[i].W;
            } else {
                lineWidth = M;
            }
        }

        writer.println(min);
    }

    /**
     * Initial the input and output.
     */
    private static void initIO() {
        try {
            scan = new Scanner(System.in);
            writer = new PrintWriter(System.out);
            // scan = new Scanner(new
            // File("E:\\workspace\\ACM\\src\\data.txt"));
            // writer = new PrintWriter(new
            // File("E:\\workspace\\ACM\\src\\test.txt"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Close the input and output.
     */
    private static void closeIO() {
        scan.close();
        writer.close();
    }
}

write answer 切换为英文 切换为中文


转发分享