[POJ3253]Fence Repair(单调队列)

题目链接

http://poj.org/problem?id=3253

题目描述

大意:切长度为a的木条的花费是a,给定最终切好的n段各自的长度,问由原来的一根木条(长度为n段长度和)以最终总花费最小的方法切这n-1下,输出最小花费。(切的中间过程产生的子段不同,所以花费会不同)

例子:
输入:
3
8 5 8
输出:
34
提示:
(8+5)+(13+8)=34

题解

  • 过程反着想,就是合并子段的过程。
  • 数据结构:两个单调递增队列。
    • 第一个放进原始的n段的长度。
    • 第二个用来放合并后的段的长度。
    • 每次贪心地选择两个队列头最小的两个段合并。合并后放入队列2头部,可以知道队列2也是单调递增的。

代码

import java.util.LinkedList;
import java.util.Scanner;

public class Main {
    public static void main(String args[]) {
        Scanner in = new Scanner(System.in);
        int n=in.nextInt();
        LinkedList<Integer> q=new LinkedList<Integer>();
        while(n--!=0) {
            q.addLast(in.nextInt());
        }
        int cost=getMinCost(q);
        System.out.println(cost);
    }
    
    public static int getMinCost(LinkedList<Integer> q) {
        q.sort(null);
        int n=q.size()-1;//切(合并)的次数
        LinkedList<Integer> sumQue=new LinkedList<>();
        int sum=0;
        while(n--!=0) {
            int tempSum=0;
            int cnt=2;
            while(cnt--!=0) {
                if(sumQue.isEmpty()||(!sumQue.isEmpty()&&!q.isEmpty()&&q.peekFirst()<=sumQue.peekFirst())) {
                    tempSum+=q.pollFirst();
                }
                else {
                    tempSum+=sumQue.pollFirst();
                }
            }
            sum+=tempSum;
            sumQue.addFirst(tempSum);
        }
        return sum;
    }
}
上一篇:126 - Incorrect key file for table ' tabname.MYI'; try to repair it


下一篇:shell 命令 grep -v