首页 > 代码库 > 帝都 Day3(by rqj)

帝都 Day3(by rqj)

备注:Day1 Day2记得笔记太233,所以就不发了

备注2:Day4~Day7发不发看心情qaq

(7.17持续更新中...)

动态规划A 记忆化搜索 & 动态规划初步

8点15: 杨姓dalao唠叨了几句;8点20:上课正式开始

part1 记忆化搜索

数字金字塔:luogu 1216

一、搜索(dfs)

没一个点向左或向右走

void dfs(int x,int y,int val)
{
    val+=a[x][y];
    if(x==n-1)
    {
        if(val>ans)ans=val;
        return;
    }
    dfs(x+1,y,val);
    dfs(x+1,y+1,val);
}

二、记忆化搜索:

冗余搜索:无用的,不会改变答案的搜索。

我们在search过程中可能会n次都走到某一个点,其中n-1次搜索即使继续搜索下去,答案也不会改变。

那么,怎么优化程序?对于每一个位置都记录一个值,代表搜到此位置时,最大路径和时多少

void dfs(int x, int y, int val)
{
    val += a[x][y];
    if(val <= f[x][y]) return;
    f[x][y] = val;
    if(x == n-1)
    {
        if(val > ans) ans = val;
        return;
    }
    dfs(x+1, y, val);
    dfs(x+1, y+1, val);
}

 背包问题:luogu 1048

一、搜索:

状态(x,w,v)——搜到第x件物品,物品总质量w,总价格v

行动——我要不要

约束——物品总质量不超过最大值

目标——物品总价值最大

冗余:(x1,w1,v1)和(x2,w2,v2)时,x1=x2,w1=w2,v1<v2,那么前者冗余

二、记忆化搜索

void dfs(int t,int x,int val)
{
    if(val<=f[t][x])return;
    f[t][x]=val;
    if(x==n)
    {
        if(val>ans)ans=val;
        return;
    } 
    dfs(t,x+1,val);
    if(t>=w[x])dfs(t-w[x],x+1,val+v[x]);
}

 其实,就是对于冗余的情况不再搜索......(这让我想起了滑雪)

part2.动态规划

在最优路径上走,每走一步都是最大值。

最优性:设走到某一个位置的时候,它达到了路径的最大值,

dp:只记录状态的最优值,并用最优值来推导其他的最优值。

记录f[i][j]路径最大值,有两种方法推导:

顺推;逆推。

数字金字塔:luogu 1216

顺推:f[i][j]->f[i+1][j]、f[i+1][j+1];

逆推:f[i-1][j];f[i-1][j-1]->f[i][j];

    //顺推
    f[0][0]=a[0][0];
    for(int i=0;i<n-1;++i)
        for(int j=0;j<=i;++j)
        {
            f[i+1][j]=max(f[i+1][j],f[i][j]+a[i+1][j]);
            f[i+1][j+1]=max(f[i+1][j+1],f[i][j]+a[i+1][j+1]);
        }
    //逆推
    f[0][0]=a[0][0];
    for(int i=0;i<n;++i)
    {
        f[i][0]=f[i-1][0]+a[i][0];
        f[i][i]=f[i-1][i-1]+a[i][i];
        for(int j=1;j<i;++j)
            f[i][j]=max(f[i-1][j-1],f[i-1][j])+a[i][j];
    }
    ans=0;
    for(int i=0;i<n;++i)
        ans=max(ans,f[n-1][i]);

 

状态转移方程

顺推:

逆推:

 

逆推改变搜索顺序

    for(int i=0;i<n;++i)
        f[n-1][i]=a[n-1][i];
    for(int i=n-2;i>=0;--i)
        for(int j=0;j<=i;++j)
            f[i][j]=max(f[i+1][j+1],f[i+1][j])+a[i][j];
    ans=f[0][0];

 这种做法不需要判断边界了

顺推、逆推依个人喜好而定(反正我喜欢逆推??????)

转移顺序:最优值之间的推导顺序

能使用dp做的题:有明确的推导顺序。数字金字塔里就有——自上而下。

能分成不同的阶段,阶段逐步进行。和搜索顺序是类似的

划分好阶段,前往后、后往前推都ok

 

帝都 Day3(by rqj)