美文网首页动态规划
2.3 记录结果再利用的“动态规划”

2.3 记录结果再利用的“动态规划”

作者: Nathanpro | 来源:发表于2015-04-06 18:11 被阅读0次

    2.3.1 记忆化搜索与动态规划

    1. 01背包问题

    <pre><code>
    //
    // Created by Nathan on 15/3/23.
    // Copyright (c) 2015年 Nathan. All rights reserved.
    //
    // 1<=n<=100;
    // 1<=wi,vi<=100;
    // 1<=W<=10000;
    // n=4;
    // (w,v) ={(2,3),(1,2),(3,4),(2,2)}
    // W=5;
    //

    include <iostream>

    using namespace std;
    int n,W;
    const int MAX = 100;
    int w[MAX],v[MAX];
    int solve(){
    int MAX_N = 100, MAX_W = 10000;
    int dp[MAX_N+1][MAX_W+1];
    for (int i =0 ; i<n; i++) {
    for (int j=0; j<=W; j++) {
    if(j>=w[i]){
    dp[i+1][j] = max( dp[i][j],dp[i][j-w[i]]+v[i]);
    } else {
    dp[i+1][j] = dp[i][j];
    }
    }
    }
    return dp[n][W];
    }
    int solve_single(){
    int MAX_W = 10000;
    int dp[MAX_W];
    for (int i=0; i<n; i++) {
    for (int j = W; j >= 0; j--) {
    if( j>=w[i] ){
    dp[j] = max(dp[j], dp[j-w[i]]+v[i] );
    }
    }
    }
    return dp[W];
    }
    int main(int argc, const char * argv[]) {
    cin >> n >> W;
    for (int i = 0; i < n; i++) {
    cin >> w[i];
    }
    for (int i = 0; i < n; i++) {
    cin >> v[i];
    }
    cout << "Solve_singe:" << solve_single() <<endl;
    cout << "Solve:" << solve() <<endl;
    return 0;
    }
    </code></pre>

    2. 最长公共子序列问题

    <pre><code>
    //
    // Created by Nathan on 15/3/25.
    // Copyright (c) 2015年 Nathan. All rights reserved.
    //
    // 1 <=n,m <=1000
    // n = 4;
    // m = 4;
    // s = 'abcd';
    // t = 'becd';
    //

    include <iostream>

    using namespace std;
    const int MAX = 1000;
    int dp[MAX+1][MAX+1];
    int n,m;
    char s[MAX],t[MAX];
    int solve(){
    for (int i = 0; i<n; i++) {
    for (int j = 0; j<m; j++) {
    if(s[i]==t[j]){
    dp[i+1][j+1] = dp[i][j]+1;
    } else {
    dp[i+1][j+1] = max(dp[i+1][j], dp[i][j+1]);
    }
    }
    }
    return dp[n][m];
    }
    int main(int argc, const char * argv[]) {
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
    cin >> s[i];
    }
    for (int i = 0; i < m; i++) {
    cin >> t[i];
    }
    cout << solve() << endl;
    return 0;
    }
    </code></pre>

    2.3.2 进一步探讨递推关系

    1. 完全背包问题1

    <pre><code>
    //
    // Created by Nathan on 15/3/27.
    // Copyright (c) 2015年 Nathan. All rights reserved.
    // 完全背包1
    // 每件物品可以挑选任意多件
    // 1 <= n <= 100
    // 1 <= wi,vi <= 100
    // 1 <= W <= 10000
    // n = 3
    // (w,v) = {(3,4),(4,5),(2,3)}
    // W = 7
    //

    include <iostream>

    using namespace std;
    const int MAX = 100;
    const int MAX_R = 10000;
    int n,W;
    int w[MAX],v[MAX];
    int solve_single(){
    int dp[MAX_R];
    for (int i = 0; i<n; i++) {
    for (int j=w[i]; j<=W; j++) {
    dp[j] = max(dp[j],dp[j-w[i]]+v[i] );
    }
    }
    return dp[W];
    }
    int solve(){
    int dp[MAX+1][MAX_R+1];
    for (int i = 0; i<n; i++) {
    for (int j = 0; j<=W; j++) {
    if( j>=w[i] ){
    dp[i+1][j] = max(dp[i][j], dp[i+1][j-w[i]]+v[i]);
    } else {
    dp[i+1][j] = dp[i][j];
    }
    }
    }
    return dp[n][W];
    }
    int main(int argc, const char * argv[]) {
    cin >> n >> W;
    for (int i =0; i<n; i++) {
    cin >> w[i];
    }
    for (int i =0; i<n; i++) {
    cin >> v[i];
    }
    cout << "Solve:" << solve() << endl;
    cout << "Solve_single:" << solve_single() << endl;
    return 0;
    }
    </code></pre>

    2. 完全背包问题2

    <pre><code>
    //
    // main.cpp
    // 2.3.2.2 Package_150328
    //
    // Created by Nathan on 15/3/28.
    // Copyright (c) 2015年 Nathan. All rights reserved.
    // 1<= n <= 100;
    // 1<= wi <= 10000000;
    // 1<= vi <= 100;
    // 1<= W <= 1000000000;
    // n = 4
    // (w,v) = {(2,3),(1,2),(3,4),(2,2)}
    // W = 5
    //

    include <iostream>

    using namespace std;
    int n,W;
    const int MAX_N = 100;
    const int MAX_V = 100;
    const int MAX_W = 10000000;
    const int INF = 1000000;
    int w[MAX_W],v[MAX_V],dp[MAX_N+1][MAX_NMAX_V+1];
    int solve(){
    fill(dp[0], dp[0]+MAX_N
    MAX_V+1, INF);
    dp[0][0]=0;
    for (int i = 0; i<n; i++) {
    for (int j = 0 ; j<=MAX_NMAX_V; j++) {
    if(j<v[i]){
    dp[i+1][j] = dp[i][j];
    } else {
    dp[i+1][j] = min(dp[i][j], dp[i][j-v[i]]+w[i]);
    }
    }
    }
    int res = 0;
    for (int i =0 ; i<=MAX_N
    MAX_V; i++) {
    if(dp[n][i]<=W){
    res = i;
    }
    }
    return res;
    }
    int main(int argc, const char * argv[]) {
    cin >> n >> W;
    for (int i = 0; i < n; i++) {
    cin >> w[i];
    }
    for (int i = 0; i < n; i++) {
    cin >> v[i];
    }
    cout << solve() << endl;
    return 0;
    }
    </code></pre>

    3. 多重部分和问题

    <pre><code>
    //
    // main.cpp
    // 2.3.2.3 Multi-section_150328
    //
    // Created by Nathan on 15/3/28.
    // Copyright (c) 2015年 Nathan. All rights reserved.
    // 3 17
    // 3 5 8
    // 3 2 2
    //

    include <iostream>

    using namespace std;
    int n,K;
    const int MAX_N = 100;
    const int MAX_K = 100000;
    int a[MAX_N],m[MAX_N];
    int dp[MAX_N+1][MAX_K+1];
    int solve(){
    dp[0][0]=true;
    for (int i=0; i<n; i++) {
    for (int j=0; j<=K; j++) {
    for (int k =0; ka[i]<=j&&k<=m[i]; k++) {
    dp[i+1][j] |= dp[i][j-k
    a[i]];
    }
    }
    }
    for (int i=0; i<=n; i++) {
    for (int j=0; j<=K; j++) {
    cout << dp[i][j] << " ";
    }
    cout << endl;
    }
    return dp[n][K];
    }
    int main(int argc, const char * argv[]) {
    cin >> n >> K;
    for (int i = 0; i<n; i++) {
    cin >> a[i];
    }
    for (int i = 0; i<n; i++) {
    cin >> m[i];
    }
    int res = solve();
    cout << res <<endl;
    return 0;
    }
    </code></pre>

    4.最长上升子序列

    <pre><code>
    //
    // main.cpp
    // 2.3.2.4 LIS_150328
    //
    // Created by Nathan on 15/3/28.
    // Copyright (c) 2015年 Nathan. All rights reserved.
    //

    include <iostream>

    using namespace std;
    const int MAX = 1000;
    int n,a[1000000];
    int dp[MAX];
    const int INF = 100000000;
    int solve_sec(){
    fill(dp, dp+n, INF);
    for (int i = 0; i<n; i++) {
    *lower_bound(dp, dp+n, a[i])=a[i];
    }
    cout << lower_bound(dp, dp+n, INF)-dp;
    return 0;
    }
    int solve(){
    int res = 0;
    for (int i =0; i<n; i++) {
    dp[i]=1;
    for (int j=0; j<i; j++) {
    if (a[j]<a[i]) {
    dp[i]=max( dp[i], dp[j]+1);
    }
    }
    res = max( res , dp[i]);
    for (int k=0; k<n; k++) {
    cout << dp[k] << " " ;
    }
    cout << endl;
    }
    return res;
    }
    int main(int argc, const char * argv[]) {
    cin >> n;
    for (int i = 0; i<n; i++) {
    cin >> a[i];
    }
    //solve_sec();
    //int res = solve_sec();
    cout << solve() << endl;
    return 0;
    }
    </code></pre>

    5. Lower_bound

    lower_bound是STL(标准模板库)中的一个函数。
    <code>lower_bound(<#_ForwardIterator __first#>, <#_ForwardIterator __last#>, <#const _Tp &_value#>)</code>
    该函数的作用是从已拍好的序列a中利用二分搜索找出指向满足ai≥k的ai指针。类似的upper_bound是找出满足ai>k的ai的最小指针。
    <pre><code>

    include <iostream>

    include <algorithm>

    include <vector>

    using namespace std;
    int main () {
    int myints[] = {10,20,30,30,20,10,10,20};
    vector<int> v(myints,myints+8); // 10 20 30 30 20 10 10 20
    sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30
    vector<int>::iterator low,up;
    low=lower_bound (v.begin(), v.end(), 10); // ^
    up= upper_bound (v.begin(), v.end(), 10); // ^
    cout << "lower_bound at position " << (low- v.begin()) << endl;
    cout << "upper_bound at position " << (up - v.begin()) << endl;
    return 0;
    }
    </code></pre>

    相关文章

      网友评论

        本文标题:2.3 记录结果再利用的“动态规划”

        本文链接:https://www.haomeiwen.com/subject/yxhzxttx.html