动态规划1

Posted showend

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划1相关的知识,希望对你有一定的参考价值。

递推

无后效性,最优子结构

-》状态转移方程     -》   注意初始化 (边界值) -》注意枚举顺序(完全背包第二维从小到大,01背包从大到小,区间先长度再左)

LIS接上之前最优解,LCS,背包问题(01背包,完全背包,分组背包,依赖性问题)

状态压缩,树形dp

看过最好的一篇讲解动态规划的

https://mp.weixin.qq.com/s/15HSidWyGg5eN--ICNNjFg

微信里的一篇文章。看完之后,基本的动态规划思想就懂了,有特点的dp需要再学习,剩下的就要刷题了。


Vijos / 题库 /

过河

数据过大,状压;
#include<iostream> #include<algorithm> #include<cstring> using namespace std; #define maxn 1000001 int a[maxn],d[maxn],v[maxn],s,t; int main() { int l,m,x; cin>>l>>s>>t>>m; memset(d,0x7f7f7f7f,sizeof(d)); for(int i=1;i<=m;i++) cin>>x,a[x]=1; v[0]=1,d[0]=0; for(int i=1;i<=l;i++) { for(int j=0;j<i;j++) { if(i-j<s||i-j>t||!v[j]) continue; v[i]=1; if(a[i]){ d[i]=min(d[i],d[j])+1; } else d[i]=min(d[i],d[j]); } } cout<<d[l]; return 0; }

Vijos / 题库 /

清帝之惑之顺治

先自顶向上,随机选取某个点i,i是由哪些点转移过来。
刚开始没想那么多,直接顺序枚举图,但结果不对,
因为如果map[i][j]的高度小于四周,四周其实目前还没有修改,仍是初始状态
等到四周的值都改了之后,又回不到该点
#include<iostream> #include<algorithm> #include<cstring> using namespace std; #define maxn 601 int ma[maxn][maxn],d[maxn][maxn]; struct m{ int x,y; int hight; }g[251000]; bool compare(m i,m j) { return i.hight>j.hight; }//将图上的高度进行排序 int main() { int r,c,ans=0,k=0; cin>>r>>c; for(int i=1;i<=r;i++) for(int j=1;j<=c;j++){ cin>>ma[i][j]; g[++k].x=i,g[k].y=j; g[k].hight=ma[i][j]; d[i][j]=1;//注意初始化,刚开始没考虑,结果就过了两个测试点 } sort(g+1,g+1+k,compare); for(int i=1;i<=k;i++)//枚举,上下左右 { int w=g[i].x,u=g[i].y; if(ma[w][u]>ma[w-1][u]&&(w-1)>0) { d[w-1][u]=max(d[w][u]+1,d[w-1][u]); } if(ma[w][u]>ma[w+1][u]&&w+1<=r) { d[w+1][u]=max(d[w][u]+1,d[w+1][u]); } if(ma[w][u]>ma[w][u-1]&&u-1>0) { d[w][u-1]=max(d[w][u]+1,d[w][u-1]); } if(ma[w][u]>ma[w][u+1]&&u+1<=c) { d[w][u+1]=max(d[w][u]+1,d[w][u+1]); } } for(int i=1;i<=r;i++) for(int j=1;j<=c;j++) ans=max(ans,d[i][j]); cout<<ans; return 0; }

 最大子矩阵和问题

#include<iostream>
#include<algorithm>
#include<cmath>
#include<set>
#include<cstring>
using namespace std;
#define max2 1111
#define rson ((pos)*2+1)
#define lson ((pos)*2)
int dp[max2],c[max2],ans=0,sum,line1[max2],line[max2],a[max2][max2],n,m;
int main()
{
    int pos1,pos2,lin1=0x3f3f3f3f,lin2=0;//pos1,pos2分别代表子矩阵起始行和末位行,lin1,lin2代表子矩阵列号
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        cin>>a[i][j];
    for(int i=1;i<=n;i++)//方法,将二维矩阵转换成一维,对于r~l行,其中每一列的元素和为b[j],此时该子矩阵的最大和相当于最大连续列的和相加即求最大连续子序列
    {
        memset(c,0,sizeof(c));
        for(int j=i;j<=n;j++){//i为子矩阵起始行,j为子矩阵末尾行
            for(int k=1;k<=m;k++)//对于行号为i,j大小的子矩阵,对其列的和进行计算
            c[k]+=a[j][k];
            int dp=0;
            for(int h=1;h<=m;h++)//连续列的最大值
            {
                if(dp>0){dp+=c[h],line1[h]=1;}
                else{memset(line1,0,sizeof(line1)),dp=c[h];line1[h]=1;}
                if(ans<dp){
                    ans=dp;
                    lin1=0x3f3f3f3f,lin2=0;
                    for(int u=1;u<=m;u++) if(line1[u]) lin1=min(lin1,u),lin2=max(lin2,u);;
                }
            }
            if(sum<ans){
                    sum=ans;
                pos1=i,pos2=j;
            }
            memset(line,0,sizeof(line));
        }
    }
   cout<<sum<<endl;
   cout<<pos1<< <<pos2<< <<lin1<< <<lin2;//输出该子矩阵的行号和列号
    return 0;
}

 

以上是关于动态规划1的主要内容,如果未能解决你的问题,请参考以下文章

应对笔试手写代码,如何准备动态规划?

应对笔试手写代码,如何准备动态规划?

算法动态规划 ⑤ ( LeetCode 63.不同路径 II | 问题分析 | 动态规划算法设计 | 代码示例 )

算法动态规划 ⑤ ( LeetCode 63.不同路径 II | 问题分析 | 动态规划算法设计 | 代码示例 )

支持动态或静态片段的不同屏幕尺寸?

算法动态规划 ① ( 动态规划简介 | 自底向上的动态规划示例 | 自顶向下的动态规划示例 )