zoukankan      html  css  js  c++  java
  • 51nod 动态规划

    基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题
     收藏
     关注
    N个整数组成的循环序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续的子段和的最大值(循环序列是指n个数围成一个圈,因此需要考虑a[n-1],a[n],a[1],a[2]这样的序列)。当所给的整数均为负数时和为0。
    例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。
     
    Input
    第1行:整数序列的长度N(2 <= N <= 50000)
    第2 - N+1行:N个整数 (-10^9 <= S[i] <= 10^9)
    Output
    输出循环数组的最大子段和。
    Input示例
    6
    -2
    11
    -4
    13
    -5
    -2
    Output示例
    20

     1 #include<bits/stdc++.H>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 int a[100010];
     6 int n;
     7 const LL inf=1e17;
     8 int main()
     9 {
    10     LL d=0;
    11     scanf("%d",&n);
    12     for(int i=0;i<n;i++) scanf("%d",&a[i]),d+=a[i];
    13     LL sum=0;
    14     LL ans1=-inf;
    15     for(int i=0;i<n;i++)
    16     {
    17         sum+=a[i];
    18         if(sum>ans1) ans1=sum;
    19         if(sum<0) sum=0;
    20     }
    21 
    22     sum=0;
    23     LL ans2=inf;
    24     for(int i=0;i<n;i++)
    25     {
    26         sum+=a[i];
    27         if(sum<ans2) ans2=sum;
    28         if(sum>0) sum=0;
    29     }
    30     printf("%lld
    ",max(ans1,d-ans2));
    31 }

    循环数组的最大字段和,有两种状态,要么是从中间截取一段,不会跨越头尾;第二种是跨越头尾,在这种情况下,最大字段和应该是从序列中取出来一个最小字段和,然后用总的减掉即可

    求最大字段和就是不断记录一个sum,用sum去更新ans

    基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题
     收藏
     关注
    N元钱换为零钱,有多少不同的换法?币值包括1 2 5分,1 2 5角,1 2 5 10 20 50 100元。
     
    例如:5分钱换为零钱,有以下4种换法:
    1、5个1分
    2、1个2分3个1分
    3、2个2分1个1分
    4、1个5分
    (由于结果可能会很大,输出Mod 10^9 + 7的结果)
    Input
    输入1个数N,N = 100表示1元钱。(1 <= N <= 100000)
    Output
    输出Mod 10^9 + 7的结果
    Input示例
    5
    Output示例
    4
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 int n;
     5 int v[20]={0,1,2,5,10,20,50,100,200,500,1000,2000,5000,10000};
     6 int dp[100010];
     7 const int mod=1e9+7;
     8 int main()
     9 {
    10     scanf("%d",&n);
    11     fill(dp,dp+n+1,1);
    12     for(int i=2;i<=13;i++)
    13     {
    14         for(int j=v[i];j<=n;j++)
    15         {
    16             dp[j]=(dp[j]+dp[j-v[i]])%mod;
    17         }
    18 
    19     }
    20     printf("%d
    ",dp[n]);
    21 }

    定义dp[i][j]为前i件物品,背包容量为j时,组合的方案数,那么dp[i][j]=sigma(dp[i-1][j-k*v[i]]),0<=k<=j/v[i],

    化简方法:dp[i][j-v[i]]=sigma(dp[i-1][j-k*v[i]]),1<=k<=j/v[i]

    那么 dp[i][j]=dp[i][j-v[i]]+dp[i-1][j]

    滚动数组,从小到大递推

    基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
     收藏
     关注
    平衡二叉树(AVL树),是指左右子树高度差至多为1的二叉树,并且该树的左右两个子树也均为AVL树。 现在问题来了,给定AVL树的节点个数n,求有多少种形态的AVL树恰好有n个节点。
    Input
    一行,包含一个整数n。 (0 < n <= 2000)
    Output
    一行表示结果,由于结果巨大,输出它对1000000007取余数的结果。
    Input示例
    10
    Output示例
    60
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 
     5 const int mod=1e9+7;
     6 
     7 int n;
     8 LL dp[2020][25];
     9 int main()
    10 {
    11     scanf("%d",&n);
    12     dp[1][1]=1;
    13     dp[0][0]=1;
    14     for(int i=1;i<=n;i++)
    15     {
    16         for(int j=1;j<=20;j++)
    17         {
    18             LL tmp=0;
    19             for(int k=0;k<=i-1;k++)
    20             {
    21                 cout<<j<<" "<<dp[k][j-2]<<endl;
    22                 tmp=(tmp+dp[k][j-1]*dp[i-1-k][j-1]+dp[k][j-1]*dp[i-1-k][j-2]+dp[k][j-2]*dp[i-1-k][j-1])%mod;
    23             }
    24             dp[i][j]=tmp;
    25         }
    26     }
    27     LL ans=0;
    28     for(int i=1;i<=20;i++)
    29         ans=(ans+dp[n][i])%mod;
    30     printf("%lld
    ",ans);
    31 }

    这里提交的是c++11标准,代码中可能访问-1下标,

    n个节点的AVL树的种类数,定义状态dp[i][j]为节点数为i, j为高度 的形态的AVL树的种类数目,

    那么dp[i][j] = dp[k][j-1] * dp[i-1-k][j-1] + dp[k][j-2] * dp[i-1-k][j-1] + dp[k][j-1]  * dp[i-1-k][j-2]  ,即为左右子树分类考虑的dp方式

    初始化 dp[0][0]=1,dp[1][1]=1;

    基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题
     收藏
     关注
    编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
    例如将kitten一字转成sitting:
    sitten (k->s)
    sittin (e->i)
    sitting (->g)
    所以kitten和sitting的编辑距离是3。俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。
    给出两个字符串a,b,求a和b的编辑距离。
     
    Input
    第1行:字符串a(a的长度 <= 1000)。
    第2行:字符串b(b的长度 <= 1000)。
    Output
    输出a和b的编辑距离
    Input示例
    kitten
    sitting
    Output示例
    3

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=1010;
     5 char a[maxn];
     6 char b[maxn];
     7 int dp[maxn][maxn];
     8 
     9 int main()
    10 {
    11     scanf("%s%s",a+1,b+1);
    12     int len1=strlen(a+1);
    13     int len2=strlen(b+1);
    14     int len=max(len1,len2);
    15     for(int i=0;i<=len;i++) dp[i][0]=dp[0][i]=i;
    16     for(int i=1;i<=len1;i++)
    17     {
    18         for(int j=1;j<=len2;j++)
    19         {
    20             dp[i][j]=min(dp[i][j-1],dp[i-1][j])+1;
    21             if(a[i]!=b[j]) dp[i][j]=min(dp[i][j],dp[i-1][j-1]+1);
    22             else dp[i][j]=min(dp[i][j],dp[i-1][j-1]);
    23         }
    24     }
    25     printf("%d
    ",dp[len1][len2]);
    26 
    27 }

    要使得两个字符串变得相同,有替换 ,插入,删除三种操作,很显然拿两个指针分别在a/b串上走,

    然后对ab所指向的字符 分别考虑是做什么操作,是替换还是插入删除

    定义dp[i][j]为a中前i个与b中前j个变得相同 应该做多少操作

    显然 dp[i][j] = min(dp[i-1][j],dp[i][j-1])+1;

    再考虑 替换操作 if ( a[i]==b[j] ) dp[i][j] = dp[i-1][j-1];

           else dp[i][j] = dp[i-1][j-1] + 1;

  • 相关阅读:
    eclipse注释乱码的一个小问题
    《java 编程思想》 读书笔记 (一)
    《java 编程思想》 读书笔记 (一)
    055_SSM——sprinMVC的返回值
    054_jQuary——html()与text()方法的区别?
    053_Servlet——resp.getWrite()与resp.getPrint()的区别?
    052_html——html转环成jsp出现乱码的问题?
    051_html——checkbox的默认值与工作属性
    050_SSM——SpringMVCV中的各个器都起了什么作用?
    047_SSM——为什么返回String使用StringHttpMessageConverter解析时会造成乱码?
  • 原文地址:https://www.cnblogs.com/hellohacker/p/7356351.html
Copyright © 2011-2022 走看看