P3173 [HAOI2009]巧克力 && P1324 矩形分割

题目描述
出于某些方面的需求,我们要把一块N×M的木板切成一个个1×1的小方块。

对于一块木板,我们只能从某条横线或者某条竖线(要在方格线上),而且这木板是不均匀的,从不同的线切割下去要花不同的代价。而且,对于一块木板,切割一次以后就被分割成两块,而且不能把这两块木板拼在一起然后一刀切成四块,只能两块分别再进行一次切割。

现在,给出从不同的线切割所要花的代价,求把整块木板分割成1×1块小方块所需要耗费的最小代价。

(n leq 10000)


错误日志: (sort) 第二个数组的时候填了第一个数组的长度。。


Solution

(totx = sum_{i = 1}^{n - 1}x_{i}, toty = sum_{i = 1}^{m - 1}y_{i})
切割横向的会对纵向的没被切割过的总和多计算一次
首先对于同为行或列的, 显然要先切权值大的, 让大的早日脱离苦海, 少计算几遍进答案
然后考虑啥时候先横向切且, 啥时候纵向切
分别写出横切和纵切的花费:

[---:(x + toty) + (y + totx - x) ]

[|:(y + totx) +(x + toty - y) ]

令前式小于后式, 计算先切x的条件:

[x + toty + y + totx - x < y + totx + x + totx - x ]

[x > y ]

所以先切 (x, y) 中花费大的即可

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
#define LL long long
#define REP(i, x, y) for(LL i = (x);i <= (y);i++)
using namespace std;
LL RD(){
    LL out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const LL maxn = 20019;
LL numx, numy;
LL x[maxn], y[maxn];
LL totx, toty;
LL ans;
bool cmp(LL a, LL b){return a > b;}
int main(){
    numx = RD(), numy = RD();
    REP(i, 1, numx - 1)x[i] = RD(), totx += x[i];
    REP(i, 1, numy - 1)y[i] = RD(), toty += y[i];
    sort(x + 1, x + numx, cmp);
    sort(y + 1, y + numy, cmp);
    LL px = 1, py = 1;
    REP(i, 1, numx + numy - 2){
        if(x[px] > y[py]){
            ans += x[px];
            totx -= x[px];
            ans += toty;
            px++;
            }
        else{
            ans += y[py];
            toty -= y[py];
            ans += totx;
            py++;
            }
        }
    printf("%lld
", ans);
    return 0;
    }
原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9846290.html