当前位置: 首页 > news >正文

【状态设计优化DP】Atcoder Beginner Contest E - Work or Rest

妈的,补完还是感觉很神秘啊

我发现我DP真的就只会写入门题呜呜呜

但是群友说abcA-G都是签到

那我大约连入门题都不会吧QwQ

题意:

一周有n天,每天除了休假就是工作,对于工作日的贡献是Amin(x,y),其中x和y是离前一个假日和后一个假日的距离,问最大贡献加起来是多少,注意哪天是休假哪天是工作是不确定的

思路:

一眼DP

一开始是这样想的:

因为哪天工作不确定,因此直接设dp[i][1]表示工作日的贡献,dp[i][0]是休假日的贡献

其实休假日并没有贡献,所以干脆直接设dp[i]为工作日i的贡献,答案就是求和

然后就不懂啊,怎么转移,因为前面和后面第一个休假日都不确定,那就去枚举两个指针?因为不止一周,怎么去处理,倍增数组吗?

然后就不会了

正解是设dp[i]为前i天且第i天休假的贡献和

感觉这个状态设的很神秘啊,但是仔细想想就会发现很妙,这样枚举一个指针就可以了

看完觉得很难受,这是咋想到的

当状态设计后发现转移的复杂度太高时,试着在状态设计的时候确定一个量,再去转移

然后去考虑转移,转移的时候考虑贡献是怎么算的

枚举完l后就得加上中间工作日的贡献

怎么O(1)算贡献?前缀和就好了

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mxn=5e3+10;
int n;
int a[mxn],dp[mxn],sum[mxn];
int cost(int l,int r){
    int len=r-l-1;
    return sum[(len+1)/2]+sum[len/2];
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i],sum[i]=sum[i-1]+a[i];
    memset(dp,128,sizeof(dp));
    dp[1]=0;
    for(int i=2;i<=n+1;i++){
        for(int j=1;j<i;j++) dp[i]=max(dp[i],dp[j]+cost(j,i));
    }
    cout<<dp[n+1]<<'\n';
}

总结:

当状态设计后发现转移的复杂度太高时,试着在状态设计的时候确定一个量,再去转移

相关文章:

  • Java的长整型Long/long后面的数字什么情况下必须加L?
  • Elasticsearch入门——kibanna和postman操作Elasticsearch索引示例
  • 【JavaEE】基于TCP的客户端服务器程序
  • 一文掌握项目估算工具及方法【管理有度13】
  • MyBatis复习
  • 智能合约审计重点
  • ZIP压缩文件如何加密?忘记密码怎么办?
  • 通过OpenDDSSharp在.NET应用程序中使用OpenDDS
  • 爆肝9万字,我已从小白晋升ARM嵌入式工程师!带你从零熟悉常用的M4嵌入式功能,建议收藏(含码源)
  • vue3.0中echarts实现中图地图的省份切换,并解决多次切换后地图卡死的情况
  • fork函数详解
  • PowerDesigner设计表时显示注释列Comment
  • SpringBoot的filter过滤器
  • Acwing---1231.航班时间
  • 小白一看就懂,交换机VLAN是如何划分的?
  • leetcode 2246. Longest Path With Different Adjacent Characters(不同相邻字母的最长路径)
  • 【蓝桥杯算法 1】AcWing166.飞行员兄弟
  • Python argparse对象与dict对象的相互转化
  • Qt图表操作(QCustomPlot 与 QtCharts的介绍与使用)
  • 代码随想录--数组相关题目整理