2021寒假集训(1)动态规划

本文介绍了动态规划的几种常见模板和优化方法,包括区间DP、概率/期望DP、状态压缩DP、数位DP、单调队列优化DP以及树状DP,并提供了相应的代码示例。这些模板和技巧在解决复杂问题时能够提高效率和准确性。
摘要由CSDN通过智能技术生成

(1)区间DP
基本模板

for(int len=2;len<=n;len++)
{       
    for(int i=1;i<n;i++)
    {
        int j=i+len-1;
        if(j>n) break;
        for(int k=i;k<=j;k++)
        {
            dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);
        } 
    }
}

(2)概率/期望dp
看缘分…

(3)状压dp
用二进制的0/1表示状态,通过遍历检查状态合法性来进行状态转移,达到最终目的

bool check(int a)
{
  	/*
  	通过对0的间距或者1的间距等条件进行判断,合法再进行状态转移
  	对于很多题目,我们还可以在初始时进行check,
  	然后将所有可行状态储存起来,
  	这样在最后写dp转移方程时可以节约大量的时间
  	*/  
}

(4)数位dp
一般用来处理区间内有多少个数字满足条件
基本套路模板

int dfs(int pos,int states,int lead,int limit)
/*
	limit传输的是这一位的数字是否为上下界
	lead代表前导0,部分题目不需要处理
	states表状态,状态数目不够可以继续增加
*/
{
    if(pos==-1)
    {
        if(/*满足条件*/) return 1;
        else return 0;
    }
    if(!limit&&!lead&&dp[pos][states]!=-1) return  dp[pos][states];
    /*
    	相同数位且相同状态时
    */
    int up=limit?num[pos]:9;//最高位为多少
    int ans=0;
    for(int i=0;i<=up;i++)
    {
        ans+=dfs(pos-1,states,lead&&i==0,limit&&num[pos]==i);
    }
    if(!limit&&!lead) dp[pos][states][nm]=ans;
    return ans;
}
int solve(int a)
{
    cnt=0;
    while(a)
    {
        num[cnt++]=a%10;
        a/=10;
        /*
        这里可以根据需要的进制来进行改变
        */
    }
    memset(dp,-1,sizeof(dp));
    return dfs(cnt-1,0,1,0,1);
}
signed main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        printf("%d\n",solve(m)-solve(n-1));
    }
    return 0;
}

(5)单调队列优化dp
首先推导出状态转移方程,
若转移方程中有一维实质上是单调增/减,
则可以把其用单调队列给优化掉
单调队列基本模板

deque<node> q;
for(int i=1;i<=m;i++)
{
    while(!q.empty()&&q.back().val>a[i])
    {
        q.pop_back();
    }
    if(!q.empty()&&i-q.front().i-id>m)
    {
        q.pop_front();
    }
    q.push_back({i,a[i]});
    ans[i]=q.front().val;
}

(6)树状dp
对一颗树进行dfs,dfs后进行状态转移

void dfs(int u,int father)
{

    for(int i=0;i<v[u].size();i++)
    {
        int tmp=v[u][i];
        if(tmp==father) continue;
        dfs(tmp,u);
        /*在这里状态更新*/
    }
    return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值