DP:数列

题目描述 Description

虽然msh长大了,但她还是很喜欢找点游戏自娱自乐。有一天,她在纸上写了一串数字:1,l,2,5,4。接着她擦掉了一个l,结果发现剩下l,2,4都在自己所在的位置上,即1在第1位,2在第2位,4在第4位。她希望擦掉某些数后,剩下的数列中在自己位置上的数尽量多。她发现这个游戏很好玩,于是开始乐此不疲地玩起来……不过她不能确定最多能有多少个数在自己的位置上,所以找到你,请你帮忙计算一下!

输入输出格式 Input/output

输入格式:
第一行为一个数n,表示数列的长度。
接下来一行为n个用空格隔开的正整数,第i行表示数Ai。
输出格式:
一行一个整数,表示擦掉某些数后,最后剩下的数列中最多能有多少个数在自己的位置上,即Ai=i最多能有多少。

输入输出样例 Sample input/output

样例测试点#1

输入样例:
5

1 1 2 5 4

输出样例:
3

说明 description
对于20%的数据,n≤20;对于60%的数据,n≤100;对于100%的数据,n≤l000。
thought of my own:f[i,j]表示前i个数删去j个数满足题意的最大值

如果init[i]=i-j,那么有删去和保留两种选择,f[i,j]:=max(f[i-1,j-1],f[i-1,j]+1)
如果init[i]<>i-j,那么也有删去和保留两种选择,f[i,j]:=max(f[i-1,j-1],f[i-1,j])

f[i,j]:=max(f[i-1,j-1],f[i-1,j]+1)         init[i]=i-j        max(f[i-1,j-1],f[i-1,j])           init[i]<>i-j
var n:longint;    init:array[1..1000]of longint;    f:array[1..1000,0..1000]of longint;    i,j,k:longint;    max:longint;
function find_max(x,y:longint):longint;         begin if x>y                  then exit(x)                  else exit(y);         end;
begin readln(n);      for i:=1 to n do          read(init[i]);      fillchar(f,sizeof(f),0);      f[1,1]:=0;      if init[1]=1         then f[1,0]:=1;      for i:=2 to n do          for j:=1 to i do              if init[i]=i-j                 then f[i,j]:=find_max(f[i-1,j]+1,f[i-1,j-1])                 else f[i,j]:=find_max(f[i-1,j-1],f[i-1,j]);
      max:=0;      for i:=0 to n do          if f[n,i]>max             then max:=f[n,i];      writeln(max);end.
时间: 2024-11-07 00:29:39

DP:数列的相关文章

最长递增子序列 (LIS) Longest Increasing Subsequence

问题描述: 有一个长为n的数列a0, a1,..., an-1.请求出这个序列中最长的上升子序列.请求出这个序列中最长的上升子序列. 上升子序列:对于任意i<j都满足ai<aj的子序列. 限制条件 i <= n <= 1000 0 <= ai <= 1000000 两种定义方式 具体看程序注释 1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #inc

最长上升子序列的两种解法

常规思路: 定义 dp[i]:=以a[i]为末尾元素的最长上升子序列的长度, 以a[i]结尾的上升序列是: 只包含a[i]的序列, 在满足j<i并且aj<ai的以aj为末尾的上升子序列末尾追加上ai得到的子序列. 两者之一. 这样递推关系:dp[i]=max(1,dp[j]+1|j<i&&a[j]<a[i])   就能在O(n^2)的时间内解决问题. 1 #include <iostream> 2 #include <cstdio> 3 #i

@atcoder - [email&#160;protected] RNG and XOR

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一个值域在 [0, 2^N) 的随机数生成器,给定参数 A[0...2^N-1]. 该生成器有 \(\frac{A_i}{\sum A}\) 的概率生成 i,每次生成都是独立的. 现在有一个 X,初始为 0.每次操作生成一个随机数 v 并将 X 异或 v. 对于每一个 i ∈ [0

Fibonacci斐波拉契数列----------动态规划DP

n==10 20 30 40 50 46 体验一下,感受一下,运行时间 #include <stdio.h>int fib(int n){ if (n<=1)     return 1; else            return fib(n-1)+fib(n-2); }int main( ){ int n; scanf("%d",&n); printf("%d\n" ,fib(n) );} 先 n==10 20 30 40 50 46

luoguP1415 拆分数列 [dp]

题目描述 给出一列数字,需要你添加任意多个逗号将其拆成若干个严格递增的数.如果有多组解,则输出使得最后一个数最小的同时,字典序最大的解(即先要满足最后一个数最小:如果有多组解,则使得第一个数尽量大:如果仍有多组解,则使得第二个数尽量大,依次类推……). 输入输出格式 输入格式: 共一行,为初始的数字. 输出格式: 共一行,为拆分之后的数列.每个数之间用逗号分隔.行尾无逗号. 输入输出样例 输入样例#1: [1] 3456 [2] 3546 [3] 3526 [4] 0001 [5] 100000

tsinsen A1067. Fibonacci数列整除问题 dp

A1067. Fibonacci数列整除问题 时间限制:1.0s   内存限制:512.0MB 总提交次数:2796   AC次数:496   平均分:51.83 将本题分享到: 查看未格式化的试题   提交   试题讨论 问题描述 已知四个数:a,b,c,d,判断在第s个Fibonacci数到第t个Fibonacci数之间哪些数既不是a也不是b也不是c也不是d的倍数. 输入格式 第一行两个数,s,t,表示要判断第s个Fibonacci数到第t个Fibonacci数之间(包含第s个和第t个)的F

bzoj2431: [HAOI2009]逆序对数列(前缀和优化dp)

2431: [HAOI2009]逆序对数列 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 2312  Solved: 1330[Submit][Status][Discuss] Description 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的 数列,可以很容易求出有多少个逆序对数.那么逆序对数为k的这样自然数数列到底有多少个? Input 第一行为两个整数n,k. Ou

【bzoj2431】[HAOI2009]逆序对数列 dp

题目描述 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的 数列,可以很容易求出有多少个逆序对数.那么逆序对数为k的这样自然数数列到底有多少个? 输入 第一行为两个整数n,k. 输出 写入一个整数,表示符合条件的数列个数,由于这个数可能很大,你只需输出该数对10000求余数后的结果. 样例输入 4 1 样例输出 3 题解 dp傻*题 设f[i][j]表示1~i组成逆序对个数为j的数列的方案数,那么考虑第i个元素,它对逆序对个

ppt Fibonacii数列的第n项------动态规划DP

#include <stdio.h>#define MAX 50+1int fib(int n){ int i,a[MAX]; a[1]=a[2]=1; for (i=3; i<=n; i++)               a[i]=a[i-1]+a[i-2];          return a[n];}void main( ){ int n; scanf("%d",&n); printf("%d\n" ,fib( n ) );} ppt

DP思想在斐波那契数列递归求解中的应用

斐波那契数列:1, 1, 2, 3, 5, 8, 13,...,即 f(n) = f(n-1) + f(n-2). 求第n个数的值. 方法一:迭代 public static int iterativeFibonacci(int n) { //简单迭代 int a = 1, b = 1; for(int i = 2; i < n; i ++) { int tmp = a + b; a = b; b = tmp; } return b; } 方法二:简单递归 public static long