24/9/10 kuangbin_dp
24_9_10 完成在kuangbin专题基础dp中的5道题
还是感觉太菜了
Max Sum Plus Plus
题意:即求最大m子段和,最大子段和的进阶
思路:我们设置为选择第j个数下分成i段的最大值,因此状态转移为
情况1:第个数单独作为一段,但是我们并不知道第 段是以什么结尾,因此是 ,情况2:第 个数不单独作为一段,那么由于连续性一定是和 同为一段,因此是
需要注意的是:这里显然可以用滚动数组优化,同时在枚举第i段时应当将和 赋值为-INF,原因是 个元素无法分成i段,对状态转移不应该有影响
void solve() {
while(~scanf("%lld%lld",&m,&n)) {
init();
for(int i = 1;i <= n;i ++ )
scanf("%lld",&a[i]);
for(int i = 1;i <= m;i ++ ) {
dp[i - 1] = -INF; //因为分成i段 i - 1个元素显然不够
for(int j = i;j <= n;j ++ ) {
dp[j] = a[j] + std::max(dp[j - 1],ma[j - 1]);
}
ma[i - 1] = -INF; //同上
for(int j = i;j <= n;j ++ ) {
ma[j] = std::max(ma[j - 1],dp[j]);
}
}
int ans = -INF;
for(int i = m;i <= n;i ++ )
ans = std::max(ans,dp[i]);
printf("%lld\n",ans);
}
}
Ignatius and the Princess IV
水题,用数组模拟同时注意数组大小就好
Super Jumping! Jumping! Jumping!
题意:在数组中每次只能走比当前更大的值,求最后的最大值
思路:设置为选择第i个数的最大值,显然有 ,类似最长不下降子序列的方式计算
void solve() {
while((std::cin >> n) && n != 0) {
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
for(int i = 1;i <= n;i ++ )
std::cin >> a[i];
for(int i = 1;i <= n;i ++ ) {
int t = -INF;
for(int j = 1;j <= i - 1;j ++ ) {
if(a[i] > a[j]) t = std::max(t,dp[j]);
}
dp[i] = a[i] + std::max(0,t);
}
int ans = -INF;
for(int i = 1;i <= n;i ++ )
ans = std::max(ans,dp[i]);
std::cout << ans << "\n";
}
}
最少拦截系统
前置知识:Dilworth定理(https://oi-wiki.org/math/order-theory/),即在偏序集中最长链的长度等于最小的反链覆盖数,对偶形式偏序集中最长反链的长度等于最小的链
的覆盖长度(oiwiki中有对偏序列,反链的说明)
思路:即题目求的是不上升子序列的最小覆盖数,数列在关系是满足自反性、传递性、反对称性,因此满足偏序集,因此问题等价为最长链的长度,即求最长上升子序列
void solve() {
while(std::cin >> n) {
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
for(int i = 1;i <= n;i ++ )
std::cin >> a[i],dp[i] = 1;
for(int i = 1;i <= n;i ++ )
for(int j = 1;j < i;j ++ ) {
if(a[j] < a[i]) dp[i] = std::max(dp[i],dp[j] + 1);
}
int ans = -INF;
for(int i = 1;i <= n;i ++ )
ans = std::max(ans,dp[i]);
std::cout << ans << "\n";
}
}
免费馅饼
思路:是典型的数塔模型,即我们按时间高低进行排列,最后都是汇集在(0,5)这个点上,直接按数塔模型计算即可
注意:可以把所有的坐标往右移动一格,避免计算位置0和11需要特殊讨论
void solve() {
while(std::cin >> n && n != 0) {
// std::cin >> n;
int t = -INF;
memset(dp,0,sizeof(dp));
for(int i = 1;i <= n;i ++ ) {
int x,y;
std::cin >> x >> y;
dp[y][++ x] ++;
t = std::max(t,y);
}
// std::cout << t << "\n";
for(int i = t;i >= 0;i -- )
for(int j = 1;j <= 11;j ++ ) {
dp[i][j] += std::max({dp[i + 1][j - 1],dp[i + 1][j],dp[i + 1][j + 1]});
}
// printf("%d\n",dp[0][6]);
std::cout << dp[0][6] << "\n";
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战