• 动态规划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;
    }
  • 相关阅读:
    算法之美_源码公布(5)
    SDL2源码分析2:窗体(SDL_Window)
    hdu5303Delicious Apples
    Android之怎样给ListView加入过滤器
    EntboostChat 0.9(越狱版)公布,iOS免费企业IM
    unix关于打包命令zip的使用
    用 query 方法 获得xml 节点的值
    用友ERP T6技术解析(六) 库龄分析
    [笔试题] 两个有趣的问题
    使用SecueCRT在本地主机与远程主机之间交互文件
  • 原文地址:https://www.cnblogs.com/Showend/p/12359310.html
Copyright © 2020-2023  润新知