差值dp 小明和广告牌
动态规划入门题
怎么看着有点像小木棍?
考虑朴素做法,我们设状态为 \(dp[i][j][k]\) 前 \(i\) 个钢筋,组成的第一根钢筋的长度为 \(j\),组成的第二根钢筋的长度为 \(k\),我们用状态储存这对组合有没有过,答案就是所有 \(j==k\) 中存在的最大的答案。
有动态转移方程:
放第一个上:\(dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-a[i]][k])\);
放第二个上:\(dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-a[i]])\);
两根都不放:\(dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k])\);
总复杂度为 \(O(sum^2\times n)\)
#include<bits/stdc++.h> using namespace std; #define ll long long const int N=1e6+10; const int mod=1e9+7; int n,sum; int dp[100][100][100]; int a[N]; int main(){ ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; sum+=a[i]; } dp[0][0][0]=1; for(int i=1;i<=n;i++){ for(int j=0;j<=sum;j++){ for(int k=0;k<=sum;k++){ dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k]); if(j>=a[i]){ dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-a[i]][k]); } if(k>=a[i]){ dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-a[i]]); } } } } int ans=0; for(int j=0;j<=sum;j++){ for(int k=0;k<=sum;k++){ if(dp[n][j][k]==1&&(j==k)){ ans=max(ans,j); } } } cout<<ans; return 0; }
但上面那个方法复杂度太大,不可以!
考虑用差值 dp,我们设状态为 \(dp[i][j]\) 为选前 i 个钢筋,第一根钢筋的长度减去第二根钢筋的长度的差,然后状态里面存放的是两根钢筋的总长度。
因为是差值,但数组肯定不能下标为负数吧,所有 \(j\) 初始转移为 \(sum\)(钢筋长度总和),在用 \(v\) 来调整边界。转移和上面的类似。
这样的复杂度就变为了 \(O(sum\times n)\)
#include<bits/stdc++.h> using namespace std; #define ll long long const int N=1e6+10; int n,sum; int dp[102][100005]; int a[102]; int main(){ ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; sum+=a[i]; } int v=0; memset(dp,-1,sizeof dp);//表示不可达 dp[0][sum]=0;//和为0 for(int i=1;i<=n;i++){ for(int j=sum-v;j<=sum+v;j++){ if(dp[i-1][j]>=0){//上一个要可达才转移 dp[i][j]=max(dp[i][j],dp[i-1][j]); dp[i][j+a[i]]=max(dp[i][j+a[i]],dp[i-1][j]+a[i]); dp[i][j-a[i]]=max(dp[i][j-a[i]],dp[i-1][j]+a[i]); } } v+=a[i];//控制和限制状态转移的范围,防止越界 } cout<<dp[n][sum]/2; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」