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;
} 

完结撒花

posted @ 2026-09-04 22:16  陈晨2011  阅读(3)  评论(0)    收藏  举报