P13018 [GESP202506 七级] 调味平衡
借鉴了洛谷题解区的第一篇题解
题目
传送门
思路
状态定义
设dp[i]为酸度的和与甜度的和的差值为i时,酸度和甜度之和的最大值。但是万一有负数的情况怎么办呢?所以我们要开一个偏移量NC,N代表数量,C代表a[i]-b[i]的最大值。所以我们的dp数组要开两倍,分为正负两边。我们的0相当于NC。
转移方程
定义x=a+b,y=a-b。
dp[i+y]=max(dp[i+y],dp[i]+x);
人话就是在目前的差值dp[i+y]和这个i+y-y也就是dp[i]+x取最大值。
分两种情况:
y<=0
这时候说明我们要从小到大遍历,尽可能的接近N*C
y>0
这时候说明我们要从大到小遍历,尽可能的接近N*C
初始化
全部的dp数组初始化为INT_MIN,除了dp[N*C]=0,因为什么都没有选择时dp[0]的最大值是0
答案
肯定是dp[N*C]啊
代码
有注释
#include<bits/stdc++.h>
using namespace std;
const int N=101,C=501;
const int D=2*N*C;
long long n,dp[D];
int main(){
cin>>n;
for(int i=0;i<D;i++)dp[i]=INT_MIN;
dp[N*C]=0;
while(n--){
long long a,b;
cin>>a>>b;
int x=a+b,y=a-b;
if(y<=0){//y<=0
for(int i=-y;i<D;i++){//这里自己思考一下循环边界
dp[i+y]=max(dp[i+y],dp[i]+x);
}
}
else{//y>0
for(int i=D-y-1;i>=0;i--){//这里自己思考一下循环边界
dp[i+y]=max(dp[i+y],dp[i]+x);
}
}
}
cout<<dp[N*C];
return 0;
}
无注释
#include<bits/stdc++.h>
using namespace std;
const int N=101,C=501;
const int D=2*N*C;
long long n,dp[D];
int main(){
cin>>n;
for(int i=0;i<D;i++)dp[i]=INT_MIN;
dp[N*C]=0;
while(n--){
long long a,b;
cin>>a>>b;
int x=a+b,y=a-b;
if(y<=0){
for(int i=-y;i<D;i++){
dp[i+y]=max(dp[i+y],dp[i]+x);
}
}
else{
for(int i=D-y-1;i>=0;i--){
dp[i+y]=max(dp[i+y],dp[i]+x);
}
}
}
cout<<dp[N*C];
return 0;
}

浙公网安备 33010602011771号