Codeforces Global Round 19 D题 Yet Another Minimization Problem(推式子,01背包变形)

题目链接

https://codeforces.com/problemset/problem/1637/D

思路

对于原式子进行推导

∑ i = 1 n ∑ j = i + 1 n ( a i + a j ) 2 + ∑ i = 1 n ∑ j = i + 1 n ( b i + b j ) 2 \sum_{i=1}^{n} \sum_{j=i+1}^{n}(a_{i}+ a_{j})^{2} + \sum_{i=1}^{n} \sum_{j=i+1}^{n}(b_{i}+ b_{j})^{2} i=1nj=i+1n(ai+aj)2+i=1nj=i+1n(bi+bj)2

= = = ∑ i = 1 n ∑ j = i + 1 n ( a i 2 + a j 2 + b i 2 + b j 2 ) + ∑ i = 1 n ∑ j = i + 1 n ( 2 × ( a i a j + b i b j ) ) \sum_{i=1}^{n} \sum_{j=i+1}^{n}(a_{i}^{2}+ a_{j}^{2}+b_{i}^{2}+b_{j}^{2}) + \sum_{i=1}^{n} \sum_{j=i+1}^{n}(2 \times (a_{i}a_{j}+b_{i}b_{j})) i=1nj=i+1n(ai2+aj2+bi2+bj2)+i=1nj=i+1n(2×(aiaj+bibj))

可以发现, ∑ i = 1 n ∑ j = i + 1 n ( a i 2 + a j 2 + b i 2 + b j 2 ) \sum_{i=1}^{n} \sum_{j=i+1}^{n}(a_{i}^{2}+ a_{j}^{2}+b_{i}^{2}+b_{j}^{2}) i=1nj=i+1n(ai2+aj2+bi2+bj2)是一个定值,我们只需要计算 ∑ i = 1 n ∑ j = i + 1 n ( 2 × ( a i a j + b i b j ) ) \sum_{i=1}^{n} \sum_{j=i+1}^{n}(2 \times (a_{i}a_{j}+b_{i}b_{j})) i=1nj=i+1n(2×(aiaj+bibj))的最小值即可。

我们定义 s u m [ i ] = ∑ j = 1 i a j + ∑ j = 1 i b j sum[i] = \sum_{j=1}^{i} a_{j} + \sum_{j=1}^{i} b_{j} sum[i]=j=1iaj+j=1ibj

考虑使用 d p dp dp。我们定义 d p [ i ] [ j ] dp[i][j] dp[i][j]表示只考虑前 i i i位时, a a a数组的背包容量为 j j j时的最小值。(先不考虑系数 2 2 2,因此最后的结果为答案的一半)。

若不交换 a i a_{i} ai b i b_{i} bi,则状态转移方程为:

d p [ i ] [ j ] = m i n ( d p [ i ] [ j ] , d p [ i − 1 ] [ j − a [ i ] ] + a [ i ] ∗ ( j − a [ i ] ) + b [ i ] ∗ ( s u m [ i − 1 ] − j + a [ i ] ) ) dp[i][j] = min(dp[i][j], dp[i - 1][j - a[i]] + a[i] * (j - a[i]) + b[i] * (sum[i - 1] - j + a[i])) dp[i][j]=min(dp[i][j],dp[i1][ja[i]]+a[i](ja[i])+b[i](sum[i1]j+a[i]))

若交换 a i a_{i} ai b i b_{i} bi,则状态转移方程为:

d p [ i ] [ j ] = m i n ( d p [ i ] [ j ] , d p [ i − 1 ] [ j − b [ i ] ] + b [ i ] ∗ ( j − b [ i ] ) + a [ i ] ∗ ( s u m [ i − 1 ] − j + b [ i ] ) ) dp[i][j] = min(dp[i][j], dp[i - 1][j - b[i]] + b[i] * (j - b[i]) + a[i] * (sum[i - 1] - j + b[i])) dp[i][j]=min(dp[i][j],dp[i1][jb[i]]+b[i](jb[i])+a[i](sum[i1]j+b[i]))

最终的答案即为: ∑ i = 1 n ∑ j = i + 1 n ( a i 2 + a j 2 + b i 2 + b j 2 ) \sum_{i=1}^{n} \sum_{j=i+1}^{n}(a_{i}^{2}+ a_{j}^{2}+b_{i}^{2}+b_{j}^{2}) i=1nj=i+1n(ai2+aj2+bi2+bj2) + + + m i n i = 1 m a x d p n , i min_{i=1}^{max}dp_{n,i} mini=1maxdpn,i

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e2 + 5, M = 1e4 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n;
int a[N], b[N], sum[N], dp[N][M];
void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	for (int i = 1; i <= n; i++)
	{
		cin >> b[i];
	}
	int ans = 0;
	for (int i = 1; i < n; i++)
	{
		for (int j = i + 1; j <= n; j++)
		{
			ans += (pow(a[i], 2) + pow(a[j], 2));
			ans += (pow(b[i], 2) + pow(b[j], 2));
		}
	}
	for (int i = 1; i <= n; i++)
	{
		sum[i] = sum[i - 1] + a[i] + b[i];
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 0; j <= 1e4; j++)
		{
			dp[i][j] = inf;
		}
	}
	dp[0][0] = 0;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= 1e4; j++)
		{
			if (j >= a[i] && (sum[i - 1] - j + a[i]) >= 0)
				dp[i][j] = min(dp[i][j], dp[i - 1][j - a[i]] + a[i] * (j - a[i]) + b[i] * (sum[i - 1] - j + a[i]));
			if (j >= b[i] && (sum[i - 1] - j + b[i]) >= 0)
				dp[i][j] = min(dp[i][j], dp[i - 1][j - b[i]] + b[i] * (j - b[i]) + a[i] * (sum[i - 1] - j + b[i]));
		}
	}
	int res = inf;
	for (int i = 1; i <= 1e4; i++)
		res = min(res, dp[n][i]);

	cout << ans + res * 2 << endl;

}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	int test = 1;
	cin >> test;
	for (int i = 1; i <= test; i++)
	{
		solve();
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值