动态规划 List

1. LCS 最长公共子序列

/* LCS
 * Au: GG
 */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1005;
int n, m, d[N][N], A[N], B[N];

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &A[i]);
    for (int i = 1; i <= m; i++) scanf("%d", &B[i]);

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            d[i][j] = max(d[i - 1][j], d[i][j - 1]);
            if (A[i] == B[j])
                d[i][j] = max(d[i][j], d[i - 1][j - 1] + 1);
        }
    }

    printf("%d\n", d[n][m]);
    return 0;
}

2. LIS 最长上升自序列

/**
 * LIS
 * Au: GG
 **/

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 1000000 + 3;
int n, a[N], d[N];
int ans;

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }

    for (int i = 1; i <= n; i++) {
        d[i] = 1;
        for (int j = 1; j < i; j++) {
            if (a[i] > a[j] && d[j] + 1 > d[i])
                d[i] = d[j] + 1;
        }
        ans = max(ans, d[i]);
    }

    printf("%d\n", ans);
    return 0;
}

3. 01 背包

// 01 Knapsack
// Au: GG

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;

int n, v, w[33], f[33][20003];

int main() {
    scanf("%d%d", &v, &n);
    for (int i = 1; i <= n; i++) scanf("%d", &w[i]);

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= v; j++) {
            if (j - w[i] < 0) f[i][j] = f[i - 1][j];
            else f[i][j] = max(f[i - 1][j - w[i]] + w[i], f[i - 1][j]);
        }
    }

    printf("%d", v - f[n][v]);

    return 0;
}

4. 完全背包

/**
 * Luogu P1616 疯狂的采药
 * Au: GG
 **/

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m, d[100000+4], w[100000+3], v[100000+3];

int main() {
    scanf("%d%d", &m, &n);
    for (int i = 1; i <= n; i++) scanf("%d%d", &v[i], &w[i]);

    for (int i = 1; i <= n; i++) {
        for (int j = v[i]; j <= m; j++) {
            d[j] = max(d[j], d[j - v[i]] + w[i]);
        }
    }

    printf("%d\n", d[m]);
    return 0;
}

5. 多维背包

/**
 * Luogu P1855 榨取kkksc03
 * Au: GG
 **/

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100 + 3, M = 200 + 3;
int n, m, t, time[N], w[N], d[N][M][M];

int main() {
    scanf("%d%d%d", &n, &m, &t);
    for (int i = 1; i <= n; i++) scanf("%d%d", &time[i], &w[i]);

    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            for (int k = 0; k <= t; k++) {
                d[i][j][k] = d[i - 1][j][k];
                if (j - time[i] >= 0 && k - w[i] >= 0 && d[i - 1][j - time[i]][k - w[i]] + 1 > d[i][j][k])
                    d[i][j][k] = d[i - 1][j - time[i]][k - w[i]] + 1;
            }
        }
    }

    printf("%d\n", d[n][m][t]);
    return 0;
}

6. 树形 DP (Unaccepted)

7. 区间 DP

/* Luogu P1880 石子合并
 * Au: GG
 */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100 + 5;
const int inf = 2147483647;
int n, d[2 * N][2 * N], e[2 * N][2 * N], a[N], sum[2 * N];
int ans1 = inf, ans2 = - inf;

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);

    for (int i = 1; i <= 2 * n; i++) sum[i] = sum[i - 1] + a[i > n ? i % n : i];

    for (int i = 1; i <= 2 * n; i++) d[i][i] = 0;
    for (int len = 2; len <= n; len++) {
        for (int i = 1; i + len - 1 <= 2 * n; i++) {
            int j = i + len - 1;
            d[i][j] = inf;
            for (int k = i; k < j; k++) {
                d[i][j] = min(d[i][j], d[i][k] + d[k + 1][j] + sum[j] - sum[i - 1]);
            }
        }
    }
    for (int i = 1; i <= n; i++) ans1 = min(ans1, d[i][i + n - 1]);

    for (int i = 1; i <= 2 * n; i++) e[i][i] = 0;
    for (int len = 2; len <= n; len++) {
        for (int i = 1; i + len - 1 < 2 * n; i++) {
            int j = i + len - 1;
            e[i][j] = - inf;
            for (int k = i; k < j; k++) {
                e[i][j] = max(e[i][j], e[i][k] + e[k + 1][j] + sum[j] - sum[i - 1]);
            }
        }
    }

    for (int i = 1; i <= n; i++) ans2 = max(ans2, e[i][i + n - 1]);

    printf("%d\n%d\n", ans1, ans2);

    return 0;
}

8. 状态压缩 DP (Unaccepted)

9. 例题 (Unaccepted)

#A 传纸条(Accepted)
    #B 乘积最大 (Unaccepted)
    #C 石子合并 (Accepted)
    #D 加分二叉树 (Unaccepted)
    #E 没有上司的舞会(Unaccepted)
    #F 选课 (Accepted)
    #G 警卫安排 (Unaccepted)
    #H 通向自由的钥匙 (Unaccepted)

时间: 2024-10-09 15:46:31

动态规划 List的相关文章

Leetcode 494 Target Sum 动态规划 背包+滚动数据

这是一道水题,作为没有货的水货楼主如是说. 题意:已知一个数组nums {a1,a2,a3,.....,an}(其中0<ai <=1000(1<=k<=n, n<=20))和一个数S c1a1c2a2c3a3......cnan = S, 其中ci(1<=i<=n)可以在加号和减号之中任选. 求有多少种{c1,c2,c3,...,cn}的排列能使上述等式成立. 例如: 输入:nums is [1, 1, 1, 1, 1], S is 3. 输出 : 5符合要求5种

活动选择的贪心算法与动态规划(未完成)

// greedy_algorithm.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include<queue> using namespace std; #define NofActivity 11 int c[NofActivity + 1][NofActivity + 1]; int reme[NofActivity + 1][NofActivity + 1]; //活动的

求不相邻金币相加和的最大值--动态规划1

求不相邻金币相加和的最大值. 输入n个金币的金币面值(正数自定义),求这些金币不相邻和的最大值. 动态规划问题1 设f(n)为第n个金币数的最大值,f(0)=0,f(1)=a[1],输入的数组从下标为1开始. f(n)=max{a[n]+f(n-2),f(n-1)}. 代码如下: import java.util.Scanner; public class Jin_bi_zui_da_zhi { public static void main(String[] args) { Scanner s

[动态规划] 黑客的攻击 Hacker&#39;s CrackDown Uva 11825

抽象为数学模型就是,  取尽可能多的互不相交的子集 ,  使得每一个子集都能覆盖全集 #include <algorithm> #include <cstring> #include <cstdio> using namespace std; int n; int P[1000],cover[1000],f[1000]; int main(){ scanf("%d", &n); for (int i = 0; i < n;i++) {

Beauty Of algorithms(七)动态规划 钢条分割 矩阵链乘 最长公共子序列 最优二叉树

1.动态规划                动态规划的方法与方法类似,英文"dynamic programming",这里的programming不是程序的意思,而是一种表格法.都是通过组合子问题的解来解决原问题,分治方法将划分为互不相交的子问题,递归的求解子问题,再将它们的解组合起来求出原问题的解.与之相反动态规划应用于子问题的重叠情况,即不同的子问题具有公共的子问题,子问题的求解是递归进行 的,将其划分为更小的子问题,动态规划,每个子问题只求解一次,将其保存在表格中,从而无需每次求

Hdoj 1176 免费馅饼 【动态规划】

免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 26110    Accepted Submission(s): 8905 Problem Description 都说天上不会掉馅饼,但有一天gameboy正走在回家的小径上,忽然天上掉下大把大把的馅饼.说来gameboy的人品实在是太好了,这馅饼别处都不掉,就掉落在他身旁的1

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

pat 1068 动态规划/Fina More Conis

1068. Find More Coins (30) Eva loves to collect coins from all over the universe, including some other planets like Mars. One day she visited a universal shopping mall which could accept all kinds of coins as payments. However, there was a special re

动态规划(4)——最长上升子序列(作业题NYOJ201)

作业题 描述 小白同学这学期有一门课程叫做<数值计算方法>,这是一门有效使用数字计算机求数学问题近似解的方法与过程,以及由相关理论构成的学科-- 今天他们的Teacher S,给他们出了一道作业题.Teacher S给了他们很多的点,让他们利用拉格朗日插值公式,计算出某严格单调函数的曲线.现在小白抄下了这些点,但是问题出现了,由于我们的小白同学上课时走了一下神,他多抄下来很多点,也就是说这些点整体连线不一定还是严格递增或递减的了.这可怎么处理呢.为此我们的小白同学制定了以下的取点规则: 1.取

动态规划之矩阵连乘

[问题描述] 给定n个矩阵{A1,A2,-,An},其中Ai与Ai+1是可乘的,i=1,2-,n-1.如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少.例如,给定三个连乘矩阵{A1,A2,A3}的维数分别是10*100,100*5和5*50,采用(A1A2)A3,乘法次数为10*100*5+10*5*50=7500次,而采用A1(A2A3),乘法次数为100*5*50+10*100*50=75000次乘法,显然,最好的次序是(A1A2)A3,乘法次数为7500次.