列表

详情


NC53870. 货物分组

描述

Venn要对货物打包。

每个货物有一定的重量,她可以用若干个箱子来装下所有的货物,但是每个箱子中物品重量总和不能超过W

Venn有一个独特的习惯,在装货过程中,某一个箱子里货物的编号必须是一个连续的区间,并且必需依次使用箱子按照物品的编号顺序装入,具体来讲编号为1的箱子一定包含1号物品,编号最大的箱子一定包含n号物品。

对于第i个箱子,如果里面装的货物总重量为w,那么费用为i*w 。

另外对于每一个箱子,在通过门卫时还会被收税,税款是箱子中重量最大的货物的重量减去重量最小的货物的重量。

她想知道,把所有货物打包并运过门卫所需要的最小费用为多少。
注:收取的税款也算作费用

点击下载大样例

输入描述

第一行两个整数n,W,分别表示货物个数以及每个箱子最大重量。

接下来一行n个正整数a_1...a_n,a_i表示编号为i的货物的重量。

输出描述

一行一个正整数表示最小费用。

示例1

输入:

5 10
5 7 8 2 1

输出:

56

说明:

每一个单独分一箱最优。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 1593ms, 内存消耗: 2724K, 提交时间: 2023-07-01 23:42:39

#include<bits/stdc++.h>
using namespace std;
const int N = 1E5 + 5;
int n;
long long a[N], w, f[N], sum[N];
int main()
{
    cin >> n >> w;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        sum[i] = sum[i - 1] + a[i];
    }
    for (int i = 1; i <= n; i++) {
        f[i] = 0x3F3F3F3F3F3F3F3F;
        long long minx = a[i], maxx = a[i];
        for (int j = i - 1; j >= 0; j--) {
            if (sum[i] - sum[j] <= w)
                f[i] = min(f[i], f[j] + sum[n] - sum[j] + maxx - minx);
            else break;
            minx = min(minx, a[j]);
            maxx = max(maxx, a[j]);
        }
    }
    cout << f[n];
}

C++11(clang++ 3.9) 解法, 执行用时: 1778ms, 内存消耗: 3168K, 提交时间: 2019-11-03 22:02:30

#include <bits/stdc++.h>
using namespace std;
int n,w;
long long f[100005],s[100005],a[100005];
long long maxx, minn;
int main() {
	cin>>n>>w;
	for(int i=1; i<=n; i++) {
		cin>>a[i];
		s[i]=s[i-1]+a[i];
	}
	for(int i=1; i<=n; i++) {
		f[i]=f[i-1]-s[i-1];
		maxx=a[i];
		minn=a[i];
		for(int j=i-2; j>=0&&s[j]>=s[i]-w; j--) {
			maxx=max(maxx,a[j+1]);
			minn=min(minn,a[j+1]);
			if(f[i]>f[j]-s[j]+maxx-minn)
				f[i]=f[j]-s[j]+maxx-minn;
		}
		f[i]+=s[n];
	}
	cout<<f[n];
}

上一题