HDU1176

    中文题意不多解释了。

    建一个二维dp数组,dp[ i ][ j ]表示第 i 秒落在 j 处一个馅饼。我们需要倒着DP,为什么呢,从 0秒,x=5处出发,假如沿数组正着往下走,终点到哪里我们是不知道的,沿这个路线能最大值,下一秒就未必是最大值。但是我们知道起点,所以我们从终点开始走,走到dp[ 0 ][ 5 ]为止。由于这个总路线存在着诸多未知情况,但是有一点我们可以确定:

        i , j

   i+1,j-1       i+1,j       i+1,j+1

    对于dp[ i ][ j ]这个点,想走到下一步,肯定要加上下一步的更大的值,这个东西是不会变的。所以从最后时间点max-1(其实从max也是可以过的)开始往上走,每次取 i ,j 的下一行三个数的最大值,再加上i,j就可以了。得到方程:

    dp【i】【j】+= max(dp【i+1】【j-1】,dp【i+1】【j】,dp【i+1】【j+1】);

    最后输出dp[0][5]这个起点就可以了。

    

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=1e5+;
int dp[maxn][];
int main()
{
int n;
while(scanf("%d",&n))
{
if(n==)
break;
memset(dp,,sizeof(dp));
int t,x;
int maxx=-;
for(int i= ;i <= n;i++)
{
scanf("%d%d",&x,&t);
dp[t][x]++;
if(t>maxx)
maxx=t;
}
for(int i=maxx-;i>=;i--)
{
for(int j=;j<=;j++)
{
int mid = max(dp[i+][j-],dp[i+][j]);
dp[i][j]+=max(mid,dp[i+][j+]);
}
}
printf("%d\n", dp[][]);
}
}

    CodeForces - 455A

     

Alex doesn't like boredom. That's why whenever he gets bored, he comes up with games. One long winter evening he came up with a game and decided to play it.

Given a sequence a consisting of n integers. The player can make several steps. In a single step he can choose an element of the sequence (let's denote it ak) and delete it, at that all elements equal to ak + 1and ak - 1 also must be deleted from the sequence. That step brings ak points to the player.

Alex is a perfectionist, so he decided to get as many points as possible. Help him.

Input

The first line contains integer n (1 ≤ n ≤ 105) that shows how many numbers are in Alex's sequence.

The second line contains n integers a1a2, ..., an (1 ≤ ai ≤ 105).

Output

Print a single integer — the maximum number of points that Alex can earn.

Examples

Input
2
1 2
Output
2
Input
3
1 2 3
Output
4
Input
9
1 2 1 3 2 2 2 2 3
Output
10

Note

Consider the third test example. At first step we need to choose any element equal to 2. After that step our sequence looks like this [2, 2, 2, 2]. Then we do 4 steps, on each step we choose any element equals to 2. In total we earn 10 points.

   题意:删除ak,那么这个数组所有的ak+1,ak-1都被删除,同时得到ak分。求能得到的最大分数。

    对每个数进行了桶排序num。这样对后面的差大于1的数没有后效性。。从0位置开始向右消去,那么要消除一个数  i   ,如果i-1被消去,那么i自然也不存在,此时dp[i] = dp[i-1],分数不变,因为i没得删。如果i-1没被删去,那么 dp[ i ] = dp[ i-2 ]+num[i]*i;

    

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+;
ll num[maxn];
ll dp[maxn];
int main()
{
ll n;
cin>>n;
int maxx=-;
int x;
for(int i=;i<=n;i++)
{
cin>>x;
num[x]++;
if(maxx<x)
maxx=x;
}
dp[]=num[];  //初始dp[1]
for(int i= ; i <= maxx; i++ )
{
dp[i]=max(dp[i-],dp[i-]+num[i]*i);
}
cout<<dp[maxx]<<endl;
}

  最长递增子序列。

  比如对于{5,6,7,4,2,8,3}  那么最长就是{5,6,7,8}长度为4.

  HDU 1257  最少拦截系统

   中文题意,求最长递增子序列。

  

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 3e4+;
typedef long long ll;
ll a[maxn];
ll dp[maxn];
int main()
{
ll n;
while(cin>>n)
{ for(int i=;i<n;i++)
cin>>a[i];
for(int i = ; i< n;i++)
dp[i]=;
ll maxx=-;
for(int i = ;i<n;i++)
{
for(int j = ; j < i ; j++)
{
if(a[i]>a[j])
{
dp[i]=max(dp[i],dp[j]+);  //还是之前的思想,选或者不选
}  
}
maxx=max(dp[i],maxx);
}
cout<<maxx<<endl;}
}

  求最长递增子序列的和

  HDU1087

  这个样例很误导人啊,这个题意呢,就是从起点跳到终点,保持递增跳而且得分最大。注意,起点和终点是不计分的;

  模板改一下就好了,之前求的是序列长度。这里求和,那么只要把dp初始化a[ ],依然还是探讨每个数选还是不选的问题。转移方程:

  if(a[i]>a[j])
  dp[ i ]=max(dp[ i ],dp[ j ]+a[ i ])

  

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 1e6+;
typedef long long ll;
ll a[maxn];
ll dp[maxn];
int main()
{
ll n ;
while(cin>>n)
{
if(n==)
break;
for(int i = ; i<n;i++)
cin>>a[i];
for(int i=;i<n;i++)
dp[i]=a[i];
ll maxx=-;
ll sum = ;
for(int i = ;i <n ; i++)
{
for(int j = ; j< i; j++)
{
if(a[i]>a[j])
{
dp[i]=max(dp[i],dp[j]+a[i]);
}
}
maxx=max(dp[i],maxx);
}
cout<<maxx<<endl;
}
}

  Comet OJ - 模拟赛 #2 Day1

   A

   我们称长度为 s 的序列  f 为波浪序列,当且仅当满足f1​≤f2​>f3​≤...或 f1​>f2​≤f3​>...且有 s≥2

   给定一个长度为 n 的序列 {a},输出其有多少个子区间满足其为波浪序列

  

  输入描述

  第 11 行包含 11 个正整数,表示序列的长度 nn

  第 22 行包含 nn 个正整数,分别表示序列中的每一个元素 a_iai​

  输出描述

  输出一行11 个正整数表示答案

  

  5
  1 2 3 2 1      
  输出
  5
  

  样例解释 1

  区间[1,2] [2,3] [3,2] [2,1] [2,3,2] 满足题意,所以共有 5 个波浪序列。

   这个题用DP解比较简单,其他的解法我并没有看懂。所谓波浪,单独一个数字不能算,两个数字一定算上。我们的二维dp,j=0表示下降或相等,j =1 表示上升。i 从0到n

   转移方程:

    

        if(a[i-]<=a[i])
{
dp[i][]=dp[i-][]+;
}
else
dp[i][]=dp[i-][]+;
sum+=dp[i][]+dp[i][];

   拿样例来解释一下:

   我们可以写出这么个东西:    0  1

            1       0  1   

            2       0  1

            3       2  0

            4       1  0

      sum逐个加就是答案。   第一步,从 i =1 开始,出现上升,则dp[1][1]=dp[0][0]+1;

                    第二步,i=2 , 2->3还是上升,但是dp[2][1]不能承接上一个dp[1][1],因为三个上升数不是波浪,需要承接dp[0][1],再加1(差不多算是重置吧)

                   第三步, i =3 ,3->2,出现下降,dp[3][0]=dp[2][1]+1=2,这里说明一下,dp[2][1]存的是2->3,+1里的这个1,是新的3->2,原来的2->3接上3->2,数目还是那个数目,既dp[3][0]=dp[2][1]+1=2。      

      总的来说,这个转移方程中,+1就是加的当前新的波浪,而上一步的dp,是之前的波浪接上了此次的新波浪,数目依然是上一个dp,但是样子已经不同了,所以要用sum进行累加。

    

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll ;
const int maxn = 3e6+;
int dp[maxn][];
int a[maxn];
int main()
{
int n ;
cin>>n;
for(int i = ; i< n ;i ++)
cin>>a[i];
ll sum = ;
for(int i = ; i< n ; i++)
{
if(a[i-]<=a[i])
{
dp[i][]=dp[i-][]+;
}
else
dp[i][]=dp[i-][]+;
sum+=dp[i][]+dp[i][];
} cout<<sum<<endl;
}

    区间DP:  

    ACWING石子合并  

    给一堆石子,相邻的合并,问最后得到的最小花费,花费具体算法在题里。

    对于此题,根据常识,对于最终状态,是由两团合并的。所以定义dp[i][j]表示区间i-j合并的最小值。

    二堆合并:dp[1][2]=dp[1][1]+dp[2][2]+sum[1~2];

         即dp[i][i+1]=dp[i][i]+dp[i+1][i+1]+sum[i~i+1];

    三堆合并:dp[1][3]=min(dp[1][1]+dp[2][3],dp[1][2]+dp[3][3])+sum[1~3];

         dp[i][i+2]=min(dp[i][i]+dp[i+1][i+2],dp[i][i+1]+dp[i+2][i+2])+sum[i~i+2];

    综上推广到第i堆到第j堆的合并,dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);

    三个for,相当于遍历每一个长度的区间。

    感觉有点floyed 的意思.....找中转点

    

#include<iostream>
#include<cstdio>
#include<cstring>
const int maxn = ;
const int inf = 1e9;
int dp[maxn][maxn];
int a[maxn],sum[maxn];
using namespace std;
int main()
{
int n;
cin>>n;
sum[]=;
for(int i = ;i <= n ; i++)
{
cin>>a[i];
sum[i]=sum[i-]+a[i];
}
for(int len = ; len <= n ;len++)
{
for(int l = ; l+len-<=n; l++)
{
int r=l+len-;
dp[l][r]=inf;
for(int k = l ; k < r ; k ++)
{
dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+][r]+sum[r]-sum[l-]);
}
}
}
cout<<dp[][n]<<endl;
}

     还是区间DP

     POJ 3280

     题意就是,给定字符串s,长度为m,由n个小写字母构成。在s的任意位置增删字母,把它变为回文串,增删特定字母的花费不同。求最小花费。

     对于样例1:  3  4

            abcb

            a  1000  1100

            b  350  700    c  200  800

          在abcb首端插入bcb花费最小。

dp学习笔记(各种dp,比较杂)的更多相关文章

  1. 数位DP学习笔记

    数位DP学习笔记 什么是数位DP? 数位DP比较经典的题目是在数字Li和Ri之间求有多少个满足X性质的数,显然对于所有的题目都可以这样得到一些暴力的分数 我们称之为朴素算法: for(int i=l_ ...

  2. DP学习笔记

    DP学习笔记 可是记下来有什么用呢?我又不会 笨蛋你以后就会了 完全背包问题 先理解初始的DP方程: void solve() { for(int i=0;i<;i++) for(int j=0 ...

  3. 树形DP 学习笔记

    树形DP学习笔记 ps: 本文内容与蓝书一致 树的重心 概念: 一颗树中的一个节点其最大子树的节点树最小 解法:对与每个节点求他儿子的\(size\) ,上方子树的节点个数为\(n-size_u\) ...

  4. [总结] 动态DP学习笔记

    学习了一下动态DP 问题的来源: 给定一棵 \(n\) 个节点的树,点有点权,有 \(m\) 次修改单点点权的操作,回答每次操作之后的最大带权独立集大小. 首先一个显然的 \(O(nm)\) 的做法就 ...

  5. 斜率优化DP学习笔记

    先摆上学习的文章: orzzz:斜率优化dp学习 Accept:斜率优化DP 感谢dalao们的讲解,还是十分清晰的 斜率优化$DP$的本质是,通过转移的一些性质,避免枚举地得到最优转移 经典题:HD ...

  6. 树形$dp$学习笔记

    今天学习了树形\(dp\),一开始浏览各大\(blog\),发现都\(TM\)是题,连个入门的\(blog\)都没有,体验极差.所以我立志要写一篇可以让初学树形\(dp\)的童鞋快速入门. 树形\(d ...

  7. 状压dp学习笔记(紫例题集)

    P3451旅游景点 Tourist Attractions 这个代码其实不算是正规题解的(因为我蒟蒻)是在我们的hzoj上内存限制324MIB情况下过掉的,而且经过研究感觉不太能用滚动数组,所以那这个 ...

  8. [学习笔记]区间dp

    区间 \(dp\) 1.[HAOI2008]玩具取名 \(f[l][r][W/I/N/G]\) 表示区间 \([l,r]\) 中能否压缩成 \(W/I/N/G\) \(Code\ Below:\) # ...

  9. [学习笔记]树形dp

    最近几天学了一下树形\(dp\) 其实早就学过了 来提高一下打开树形\(dp\)的姿势. 1.没有上司的晚会 我的人生第一道树形\(dp\),其实就是两种情况: \(dp[i][1]\)表示第i个人来 ...

随机推荐

  1. Vue - 引入本地图片的两种方式

    第一种,只引入单个图片,这种引入方法在异步中引入则会报错. 比如需要遍历出很多图片展示时 <image :src = require('图片的路径') /> 第二种,可引入多个图片,也可引 ...

  2. struts2--通配符映射

    1.通配符映射: --规则: > 1)若找到多个匹配,没有通配符的优先: > 2)若指定动作不存在,struts2将会尝试把这个URI与任何一个包含着通配符*的动作名进行匹配: > ...

  3. 原生JS获取所有标签的数量并统计每个标签的数量

    <script type="text/javascript"> var tags = document.getElementsByTagName('*'); var t ...

  4. 修剪草坪 HYSBZ - 2442

    在一年前赢得了小镇的最佳草坪比赛后,FJ变得很懒,再也没有修剪过草坪.现在,新一轮的最佳草坪比赛又开始了,FJ希望能够再次夺冠. 然而,FJ的草坪非常脏乱,因此,FJ只能够让他的奶牛来完成这项工作.F ...

  5. 卸载重装ngin的问题解决方案

    1,卸载nginx不保留配置文件 $ sudo apt-get --purge remove nginx 2,卸载自动安装且不再需要的依赖包 $ sudo apt-get autoremove 3,卸 ...

  6. Day8 - G - Bound Found ZOJ - 1964

    Signals of most probably extra-terrestrial origin have been received and digitalized by The Aeronaut ...

  7. 洛谷题解P1047 校门外的树

    题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,…,L,都种有 ...

  8. 数据结构——java Queue类

    定义 队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作. LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用 图例 Que ...

  9. ConfigureDefender – Windows Defender 设置工具

    用于配置Windows 10内置Defender防病毒设置的实用程序.它是一个便携式实用程序 ConfigureDefender实用程序是一个GUI应用程序,用于在Windows 10上查看和配置重要 ...

  10. Dive into re Module in Python

    Dive into RE in Python Standard re module in python is powerful to handle text manipulation,such as ...