[POI2003]Chocolate 题解

[POI2003]Chocolate 题解

题目地址:BZOJ:Problem 2430. — [Poi2003]Chocolate

题目描述

有一块n*m的矩形巧克力,准备将它切成n*m块。巧克力上共有n-1条横线和m-1条竖线,你每次可以沿着其中的一条横线或竖线将巧克力切开,无论切割的长短,沿着每条横线切一次的代价依次为y1,y2,…,yn-1,而沿竖线切割的代价依次为x1,x2,…,xm-1。例如,对于下图6*4的巧克力,
11(2) - [POI2003]Chocolate 题解
我们先沿着三条横线切割,需要3刀,得到4条巧克力,然后再将这4条巧克力沿竖线切割,每条都需要5刀,则最终所花费的代价为y1+y2+y3+4*(x1+x2+x3+x4+x5)。
当然,上述简单切法不见得是最优切法,那么怎样切割该块巧克力,花费的代价最少呢?

题意简述

要把一个大矩形横着切n-1刀竖着切m-1刀分成n*m个小矩形,从左到右从上到下每个位置切一刀都有一个代价,每一次对一整块(不论大小,无法一刀切断多块)切一次都会产生一次代价,求切割的最小代价。

输入输出格式

输入格式:
第一行为两个整数n和m。
接下来n-1行,每行一个整数,分别代表x1,x2,…,xn-1。
接下来m-1行,每行一个整数,分别代表y1,y2,…,ym-1。

输出格式:
输出一整数,为切割巧克力的最小代价。

输入输出样例

输入样例#1:

6 4
2
1
3
1
4
4
1
2

输出样例#1:

42

说明

30%的数据,n<=100,m<=100
100%的数据,n<=10000,m<=10000

题解

贪心。
一定是先切掉代价较大的位置。考虑证明它,对于平行的刀切位置,在一个序列中先切代价大的,由于每一刀要乘上与位置垂直的位置已经切了几刀这个数字,因此越靠前乘的数字越小,总和越小。对于垂直的两个刀切位置,先切代价较大的那个,若先切较小的,较大的乘的数字会+1,比先切较大的更劣。
由于需要排序,复杂度O(n \log n)

代码

// Code by KSkun, 2018/6
#include <cstdio>
#include <cctype>

#include <algorithm>
#include <vector>
#include <functional>

typedef long long LL;

inline char fgc() {
    static char buf[100000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
        ? EOF : *p1++;
}

inline LL readint() {
    register LL res = 0, neg = 1; register char c = fgc();
    for(; !isdigit(c); c = fgc()) if(c == '-') neg = -1;
    for(; isdigit(c); c = fgc()) res = (res << 1) + (res << 3) + c - '0';
    return res * neg;
}

const int MAXN = 20005;

struct Node {
    int w;
    bool type;
    inline bool operator>(const Node &rhs) const {
        return w > rhs.w;
    }
};

int n, m;
std::vector<Node> vec;

int main() {
    n = readint(); m = readint();
    for(int i = 1, t; i < n; i++) {
        t = readint(); vec.push_back(Node {t, 0});
    }
    for(int i = 1, t; i < m; i++) {
        t = readint(); vec.push_back(Node {t, 1});
    }
    std::sort(vec.begin(), vec.end(), std::greater<Node>());
    int ch = 1, cv = 1, ans = 0;
    for(int i = 0; i < vec.size(); i++) {
        ans += vec[i].w * (vec[i].type ? ch : cv);
        if(vec[i].type) cv++; else ch++;
    }
    printf("%d", ans);
    return 0;
}


发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据