码迷,mamicode.com
首页 > 其他好文 > 详细

动态规划专题之线性dp

时间:2020-07-11 12:37:35      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:string   perm   告诉   ng2   mem   set   最长上升子序列   严格   http   

POJ2279 Mr. Young‘s Picture Permutations
 
有N个学生合影,站成左对齐的k排,每行分别有N1,N2…NK个人,第一排站最后,第k排站之前。
学生身高依次是1…N。在合影时候要求每一排从左到右递减,每一列从后面到前也递减,一共有多少总方案

Input

输入
每组测试数据包含两行。第一行给出行数k
第二行包含从后到前(n1,n2,…,nk)的行的长度,作为由单个空格分隔的十进制整数。
问题数据以0结束。
N<=30, k<=5;

Output

输出
输出每组数据的方案数

Sample Input

1
30
5
1 1 1 1 1
3
3 2 1
4
5 3 3 1
5
6 5 4 3 2
2
15 15
0

Sample Output

1
1
16
4158
141892608
9694845
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 31;
typedef long long LL;
int a[N];
int main() {
    int k;
    while (scanf("%d", &k) && k) {
        for (int i = 0; i < k; i++) {
            scanf("%d", &a[i]);
        }
        for (int i = k; i < 5; i++)
            a[i] = 0;
        LL dp[a[0] + 1][a[1] + 1][a[2] + 1][a[3] + 1][a[4] + 1];
        memset(dp, 0, sizeof(dp));
        dp[0][0][0][0][0] = 1;
        for (int a1 = 0; a1 <= a[0]; a1++) {
            for (int a2 = 0; a2 <= a[1]; a2++) {
                for (int a3 = 0; a3 <= a[2]; a3++) {
                    for (int a4 = 0; a4 <= a[3]; a4++) {
                        for (int a5 = 0; a5 <= a[4]; a5++) {
                            if (a1 < a[0]) {
                                dp[a1 + 1][a2][a3][a4][a5] += dp[a1][a2][a3][a4][a5];
                            }
                            if (a2 < a[1] && a1 > a2) {
                                dp[a1][a2 + 1][a3][a4][a5] += dp[a1][a2][a3][a4][a5];
                            }
                            if (a3 < a[2] && a2 > a3 && a1 >= a2) {
                                dp[a1][a2][a3 + 1][a4][a5] += dp[a1][a2][a3][a4][a5];
                            }
                            if (a4 < a[3] && a3 > a4 && a1 >= a2 && a2 >= a3) {
                                dp[a1][a2][a3][a4 + 1][a5] += dp[a1][a2][a3][a4][a5];
                            }
                            if (a5 < a[4] && a4 > a5 && a1 >= a2 && a2 >= a3 && a3 >= a4) {
                                dp[a1][a2][a3][a4][a5 + 1] += dp[a1][a2][a3][a4][a5];
                            }
                        }
                    }
                }
            }
        }
        printf("%lld\n", dp[a[0]][a[1]][a[2]][a[3]][a[4]]);
    }
    return 0;
}

 

Acwing272 最长公共上升子序列

熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目。

小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们研究最长公共上升子序列了。

小沐沐说,对于两个数列A和B,如果它们都包含一段位置不一定连续的数,且数值是严格递增的,那么称这一段数是两个数列的公共上升子序列,而所有的公共上升子序列中最长的就是最长公共上升子序列了。

奶牛半懂不懂,小沐沐要你来告诉奶牛什么是最长公共上升子序列。

不过,只要告诉奶牛它的长度就可以了。

数列A和B的长度均不超过3000。

输入格式

第一行包含一个整数N,表示数列A,B的长度。

第二行包含N个整数,表示数列A。

第三行包含N个整数,表示数列B。

输出格式

输出一个整数,表示最长公共上升子序列的长度。

数据范围

1N30001≤N≤3000,序列中的数字均不超过2311231−1

输入样例:

4
2 2 1 3
2 1 2 3

输出样例:

2
#include<bits/stdc++.h>
using namespace std;
const int N = 3e3 + 7;
int dp[N][N], a[N], b[N], n;
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) cin >> b[i];
    for (int i = 1; i <= n; i++) {
        int val = 0;
        for (int j = 1; j <= n; j++) {
            if (a[i] == b[j]) dp[i][j] = val + 1;
            else dp[i][j] = dp[i - 1][j];
            if (b[j] < a[i]) val = max(val, dp[i - 1][j]);
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            ans = max(ans, dp[i][j]);
        }
    }
    printf("%d\n", ans);
    return 0;
}

 

 

动态规划专题之线性dp

标签:string   perm   告诉   ng2   mem   set   最长上升子序列   严格   http   

原文地址:https://www.cnblogs.com/HighLights/p/13283080.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!