Dima and Salad
Posted TURNINING
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dima and Salad相关的知识,希望对你有一定的参考价值。
题意:有n个物品,每个物品有两种属性 a i a_i ai, b i b_i bi,要求最大的 ∑ i m a i \\sum_i^{m}a_i ∑imai且 ∑ i m a i / ∑ i m b i = k \\sum_i^{m}a_i/\\sum_i^{m}b_i = k ∑imai/∑imbi=k;
思路:把式子整理一下: ∑ i m a i − k ∗ ∑ i m b i = 0 \\sum_i^{m}a_i-k*\\sum_i^{m}b_i = 0 ∑imai−k∗∑imbi=0 我们把每个物品对答案的贡献转换为 a i − k ∗ b i a_i-k*b_i ai−k∗bi,问题就变成了 求总贡献为0时 ∑ i m a i \\sum_i^{m}a_i ∑imai的最大值。
因为贡献有正有负,我们把正负的情况分开求 最终问题变为贡献相同时正负所能取到的最大价值之和的最大值。
转换为了01背包,注意保证状态转移时背包是被填满的。
#include<bits/stdc++.h>
using namespace std;
#define lsn (u << 1)
#define rsn (u << 1 | 1)
#define mid (l + r >> 1)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
const int MAXN = 100 + 10;
const int MAX_LEN = 1e5 + 10;
const int MAX_LOG_V = 22;
const ll INF = 1e17;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-7;
const ull B = 100000007;
int n, k;
int a[MAXN], b[MAXN];
int dp1[MAX_LEN], dp2[MAX_LEN];
int a1[MAXN], a2[MAXN];
int b1[MAXN], b2[MAXN];
void solve() {
scanf("%d %d", &n, &k);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
int tot1 = 0, tot2 = 0;
for(int i = 1; i <= n; i++) {
if(a[i]-k*b[i] >= 0) {
a1[++tot1] = a[i];
b1[tot1] = a[i]-k*b[i];
}
else {
a2[++tot2] = a[i];
b2[tot2] = -(a[i]-k*b[i]);
}
}
for(int i = 1; i <= tot1; i++) {
for(int j = MAX_LEN - 1; j >= b1[i]; j--) {
if(j-b1[i] == 0 || dp1[j-b1[i]])
dp1[j] = max(dp1[j], dp1[j-b1[i]]+a1[i]);
}
}
for(int i = 1; i <= tot2; i++) {
for(int j = MAX_LEN - 1; j >= b2[i]; j--) {
if(j-b2[i] == 0 || dp2[j-b2[i]])
dp2[j] = max(dp2[j], dp2[j-b2[i]]+a2[i]);
}
}
int ans = dp1[0];
for(int i = 1; i <= 1e5; i++) {
if(dp1[i] && dp2[i]) ans = max(ans, dp1[i]+dp2[i]);
}
if(ans == 0) puts("-1");
else printf("%d\\n", ans);
}
int main() {
//ios::sync_with_stdio(false);
int t = 1; //scanf("%d", &t);
while(t--) {
solve();
}
return 0;
}
以上是关于Dima and Salad的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 366C Dima and Salad