[hdu4513]常规dp

题意:给一个长度为m的序列,从里面选出一些数,相对位置不发生变化,并满足a[i]=a[n-i],a[1]<a[2]<...<a[(n+1)/2],n是数的个数,求最大的n

思路:dp[i][j]表示0~i,j~m的答案,则dp[i][j]=dp[l][r]+1+(i<j),其中a[i]=a[j]>a[l]=a[r]&&l<i<=j<r。枚举3个变量i,j,r,维护一个l就行了,o(m^3)。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

/* ******************************************************************************** */

#include <iostream>                                                                 //

#include <cstdio>                                                                   //

#include <cmath>                                                                    //

#include <cstdlib>                                                                  //

#include <cstring>                                                                  //

#include <vector>                                                                   //

#include <ctime>                                                                    //

#include <deque>                                                                    //

#include <queue>                                                                    //

#include <algorithm>                                                                //

using namespace std;                                                                //

                                                                                    //

#define pb push_back                                                                //

#define mp make_pair                                                                //

#define X first                                                                     //

#define Y second                                                                    //

#define all(a) (a).begin(), (a).end()                                               //

#define foreach(i, a) for (typeof(a.begin()) it = a.begin(); it != a.end(); it ++)  //

                                                                                    //

void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}    //

void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>                    //

void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;          //

while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>      //

void print(const T t){cout<<t<<endl;}template<typename F,typename...R>              //

void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>   //

void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}   //

                                                                                    //

typedef pair<intint> pii;                                                         //

typedef long long ll;                                                               //

typedef unsigned long long ull;                                                     //

                                                                                    //

/* -------------------------------------------------------------------------------- */

                                                                                    //

template<typename T>bool umax(T &a, const T &b) {

    return a >= b? false : (a = b, true);

}

int a[300], dp[300][300];

int main() {

#ifndef ONLINE_JUDGE

    freopen("in.txt""r", stdin);

#endif // ONLINE_JUDGE

    int T;

    RI(T);

    while (T --) {

        int n;

        RI(n);

        RI(a + 1, a + 1 + n);

        int p[300] = {};

        memset(dp, 0, sizeof(dp));

        int ans = 0;

        for (int i = 1; i <= n; i ++) {

            for (int j = n; j >= i; j --) {

                if (a[i] != a[j]) continue;

                dp[i][j] = 1 + (i < j);

                for (int k = j + 1; k <= n; k ++) {

                    if (a[k] < a[i]) {

                        if (p[a[k]] && p[a[k]] < i)

                            umax(dp[i][j], dp[p[a[k]]][k] + 1 + (i < j));

                    }

                }

                umax(ans, dp[i][j]);

            }

            p[a[i]] = i;

        }

        cout << ans << endl;

    }

    return 0;                                                                       //

}                                                                                   //

                                                                                    //

                                                                                    //

                                                                                    //

/* ******************************************************************************** */

时间: 2024-08-01 06:28:15

[hdu4513]常规dp的相关文章

hdu 2571 dp入门题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2571 常规dp,刚好让我这菜鸟来找找 找状态转移方程的感觉.. 定义dp[i][j]  表示的是第i行j列所拥有的最大的幸运值. dp[i][j] 由三种情况转移而来:1.从上面一个坐标转移而来,即dp[i-1][j] .2.由左边转移过来,即dp[i][j-1].3.由他同一行中的 j 的因数列转移过来的(但是要除了j自己),即dp[i][ j 的因数列] 找出这三种情况中最大的就可以了,dp[i

HihoCoder1339 Dice Possibility(概率DP+母函数)

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 What is possibility of rolling N dice and the sum of the numbers equals to M? 输入 Two integers N and M. (1 ≤ N ≤ 100, 1 ≤ M ≤ 600) 输出 Output the possibility in percentage with 2 decimal places. 样例输入 2 10 样例输出 8.3

【BZOJ】1597 [Usaco2008 Mar]土地购买

[算法]DP+斜率优化 [题意]n(n≤50000)块土地,长ai宽bi,可分组购买,每组代价为max(ai)*max(bi),求最小代价. [题解] 斜率优化:http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html 因为对于土地x和y,若满足a[x]<=a[y]&&b[x]<=b[y],则x土地可无条件包含在y土地中,所以x土地可以忽略. 于是对长度从小到大排序,第二关键字对宽度从小到大排序,处理掉可被包

BZOJ 1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚

题目 1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚 Time Limit: 5 Sec  Memory Limit: 64 MB Description Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now require their barn to be immaculate. Farmer John, the most

【Unique Paths】cpp

题目: A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish'

FZU 1977 Pandora adventure (插头DP,常规)

题意:有一个n*m矩阵,其中有些格子必走,有些格子不可走,其他格子是可走也可不走,问有多少条哈密顿回路? 思路: 本来是一道很简单的题,代码写多了连白痴bug都查不出了,竟然用i>=ex&&j>=ey来判定最后一个必走点后面的点!明显是错的. 其实主要在选走的格子,那么有两种选择,“走”or“不走”,不走的话上一个格子的状态照搬过来.这样就没有了固定的终点了,因为终点可以是很多种情况(比如是选走点/必走点),那么只要是在ex和ey后面的格子(指的是(ex,ey)之后遍历的所有非

HDU 1561 The more, The Better (树形DP,常规)

题意:给一个森林,n个节点,每个点有点权,问若从中刚好选择m个点(选择某点之前必须先选择了其父亲),使得这m个点权之和最大为多少? 思路: 比较常规.就是DFS一次,枚举在子树中可能选择的k个点(注意上限为min(子树节点数,到此子树最多可选节点数)),需要注意的是dp[t][1]必须是点t自己,枚举的时候必须先选择t才能选择t的孩子.但是本题是森林,那么可以建1个虚拟根编号为0(根输入一模一样),然后虚拟根的权为0即可,而所要选的数就变成m+1了. 1 #include <bits/stdc+

URAL 1519 Formula 1 (插头DP,常规)

题意:给一个n*m的矩阵,格子中是'*'则是障碍格子,不允许进入,其他格子都是必走的格子,所走格子形成一条哈密顿回路,问有多少种走法? 思路: 本来是很基础的题,顿时不知道进入了哪个坑.这篇插头DP的文章够详细,推荐一看(最好不要照抄代码). 细节要小心,比如输出用I64d,必须用long long,判断是否无哈密顿回路,位操作等等. 这次仍然用括号表示法,1表示(,2表示). 1 #include <bits/stdc++.h> 2 #define pii pair<int,int&g

luoguP1415 拆分数列 [dp]

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