zoukankan      html  css  js  c++  java
  • 动态规划算法例题

    1. 走台阶问题

    有n级台阶,一个人每次上一级或者两级,问有多少种走完n级台阶的方法?

    方法1:递归

    #include <iostream>
    using namespace std;

    const int N = 100; //假设最多走100级台阶
    int result[N]; //保存结果

    int step(int n)
    {
    if(n > 2)
    {
    result[n] = step(n-1) + step(n-2);
    }
    return result[n];
    }

    int main()
    {
    int n;
    cin >> n;
    result[1] = 1;
    result[2] = 2;
    cout << step(n) << endl;
    system("pause");
    return 0;
    }

    方法2:自底向上

    #include <iostream>
    using namespace std;

    const int N = 100; //假设最多走100级台阶
    int result[N]; //保存结果

    int step(int n)
    {
    for(int i = 3; i <= n; i++)
    {
    result[i] = result[i-1] + result[i-2];
    }
    return result[n];
    }

    int main()
    {
    int n;
    cin >> n;
    result[1] = 1;
    result[2] = 2;
    cout << step(n) << endl;
    system("pause");
    return 0;
    }

    2. 求斐波拉契数列Fibonacci

    方法1:递归

    #include <iostream>
    using namespace std;

    const int N = 101; //假设最多求到100
    int result[N]; //保存结果

    int fb(int n)
    {
    if(n >= 2)
    {
    result[n] = fb(n-1) + fb(n-2);
    }
    return result[n];
    }

    int main()
    {
    int n;
    cin >> n;
    result[0] = 0;
    result[1] = 1;
    cout << fb(n) << endl;
    system("pause");
    return 0;
    }

    方法2:自底向上

    #include <iostream>
    using namespace std;

    const int N = 101; //假设最多求到100
    int result[N]; //保存结果

    int fb(int n)
    {
    for (int i = 2; i <= n; i++)
    {
    result[i] = result[i-1] + result[i-2];
    }
    return result[n];
    }

    int main()
    {
    int n;
    cin >> n;
    result[0] = 0;
    result[1] = 1;
    cout << fb(n) << endl;
    system("pause");
    return 0;
    }

    3. 拼凑面额

    给你六种面额1、5、10、20、50、100元的纸币,假设每种币值的数量都足够多,编写程序求组成N元(N为0-10000的非负整数)的不同组合的个数。

    输入为一个数字N,即需要拼凑的面额。输出也是一个数字,为组成N的组合个数。

    #include<iostream>
    #include<vector>
    using namespace std;

    int a[6] = {1, 5, 10, 20, 50, 100};
    int main()
    {
    int n;
    cin >> n;
    vector<long> dp(n+1, 1);
    for(int i = 1; i < 6; i++)
    {
    for(int j = 1; j <= n; j++)
    {
    if(j >= a[i])
    {
    dp[j] = dp[j] + dp[j-a[i]];
    }
    }
    }
    cout << dp[n];
    system("pause");
    return 0;
    }

    4.

    给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。 

    输入为两行:    第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)第二行为n个正整数A[i](32位整数),以空格隔开。

    输出所求的方案数。

    输入:

    5 15

    5 5 10 2 3

    输出

    4

    用动态规划, dp(i , j )表示前i 个数中和为 j 的方案数, 则 若 j >= a[i],  dp( i ,j) = dp(i -1, j)+ dp(i - 1,j - a[i] );

    否则,  f ( i ,j) = f(i -1, j)。

    #include <iostream>
    #include <vector>
    using namespace std;

    long dp[1001][1001];
    int main()
    {
    int n, sum;
    cin >>n >> sum;
    vector<int> A(n+1, 0);

    for(int i = 1; i <= n; i++)
    {
    cin >> A[i];
    }
    for (int i = 0; i <= n; i++)
    {
    for(int j = 0; j <= sum; j++)
    {
    dp[i][j] = 0;
    }
    }
    dp[0][0] = 1;
    for(int i = 1; i <= n; i++)
    {
    for(int j = 0; j <= sum; j++)
    {
    if (j >= A[i])
    {
    dp[i][j] = dp[i-1][j] + dp[i-1][j-A[i]];
    }
    else
    {
    dp[i][j] = dp[i-1][j];
    }
    }
    }
    cout << dp[n][sum];
    system("pause");
    return 0;
    }

    优化的方法为:由于二维数组中,第i行 只与第 i - 1 行有关,所有我们若从 最后一列 开始更新数组,则可用一维数组来保存先前状态。

    #include <iostream>
    #include <vector>
    using namespace std;

    int main()
    {
    int n, sum;
    cin >>n >> sum;
    vector<int> A(n+1, 0);
    vector<long> dp(sum+1, 0);
    for(int i = 1; i <= n; i++)
    {
    cin >> A[i];
    }
    dp[0] = 1;
    for(int i = 1; i <= n; i++)
    {
    for(int j = sum; j >= A[i]; j--)
    {
    dp[j] = dp[j] + dp[j-A[i]];
    }
    }
    cout << dp[sum];
    system("pause");
    return 0;
    }

    5.

    #include<iostream>
    #include <vector>
    #include <time.h>
    using namespace std;
    /*
    在一条直线上,有n个房屋,每个房屋中有数量不等的财宝,有一个盗贼希望从房屋中盗取财宝,由于房屋中有报警器,
    如果同时从相邻的房屋中盗取财宝就会触发报警器。问不触发报警器的前提下,最多可获取多少财宝

    输入 [5 2 6 3 1 7] 输出 5 + 6 + 7 = 18
    */
    int rob(vector<int> &nums)
    {
    //设dp[i]为前i个房屋中可获取的财宝, dp[i] = max{dp[i-1], dp[i-2] + nums[i]}
    vector<int> dp(nums.size() + 1, 0);
    dp[0] = 0;
    dp[1] = nums[0];
    for (int i = 2; i < nums.size() + 1; i++)
    {
    if (dp[i-1] > dp[i-2] + nums[i-1])
    {
    dp[i] = dp[i-1];
    }
    else
    {
    dp[i] = dp[i-2] + nums[i-1];
    }
    }
    return dp[nums.size()];
    }
    int main()
    {
    vector<int> nums(6);
    srand((unsigned int)time(NULL));
    for (int i = 0; i < 6; i++)
    {
    nums[i] = rand() % 20 + 1;
    cout << nums[i] << " ";
    }
    cout << endl;
    cout << rob(nums) << endl;
    system("pause");
    return 0;
    }

    6.

    #include<iostream>
    #include <vector>
    #include <time.h>
    using namespace std;
    /*
    给定一个数组,求这个数组的连续子数组中,最大的那一段的和
    如数组[-2, 1, -3, 4, -1, 2, 1, -5, 4] , 最大的和是[4, -1, 2, 1], 为6
    */
    int maxSubArray(vector<int> &nums)
    {
    //设dp[i]为包含第i项的最大子列和
    //dp[i-1] > 0, 则dp[i] = dp[i-1] + nums[i]. 否则 dp[i] = nums[i]
    vector<int> dp(nums.size(), 0);
    int max_res = nums[0];
    dp[0] = nums[0];
    for (int i = 1; i < nums.size(); i++)
    {
    if (dp[i-1] > 0)
    {
    dp[i] = dp[i-1] + nums[i];
    }
    else
    {
    dp[i] = nums[i];
    }
    if (max_res < dp[i])
    {
    max_res = dp[i];
    }
    }

    return max_res;
    }
    int main()
    {
    vector<int> nums(8);
    srand((unsigned int)time(NULL));
    for (int i = 0; i < 8; i++)
    {
    nums[i] = rand() % 10 - 5;
    cout << nums[i] << " ";
    }
    cout << endl;
    cout << maxSubArray(nums) << endl;
    system("pause");
    return 0;
    }

    #include<iostream>
    #include <vector>
    #include <time.h>
    using namespace std;
    /*
    已知不同面值的钞票,求如何用最少数量的钞票组成某个金额,求可以使用的最少钞票数量,
    如果任意数量的已知面额钞票都无法组成该金额,则返回-1

    [1, 2, 5] 11 返回3
    [2] 3 返回-1
    [1, 2, 5, 7, 10] 14 返回2
    */
    int coinChange(vector<int> &coins, int amount)
    {
    //设dp[i]为面额为i 的最少钞票个数
    //若dp[i-coins[j]]全为-1, 则返回-1, 否则 dp[i] = 1 + max(dp[i-coins[j]])
    vector<int> dp(amount+1, -1);
    dp[0] = 0;
    for (int i = 1; i < amount + 1; i++)
    {
    for (int j = 0; j < coins.size(); j++)
    {
    if (i >= coins[j] && dp[i-coins[j]] != -1 && (dp[i] == -1 || dp[i] > dp[i-coins[j]] + 1))
    {
    dp[i] = dp[i-coins[j]] + 1;
    }
    }
    }
    return dp[amount];
    }
    int main()
    {
    vector<int> nums(5);
    srand((unsigned int)time(NULL));
    for (int i = 0; i < 5; i++)
    {
    nums[i] = rand() % 10 + 1;
    cout << nums[i] << " ";
    }
    cout << endl;
    cout << coinChange(nums, 13) << endl;
    system("pause");
    return 0;
    }

    #include<iostream>
    #include <vector>
    #include <time.h>
    using namespace std;
    /*
    给定一个二维数组,其保存了一个数字三角形,求从数字三角形顶端到低端各数字和最小的路径之和,
    每次可以向下走相邻的两个位置

    [2]
    [3, 4]
    [6, 5, 7]
    [4, 1, 8, 3]
    返回11

    */
    int minimumTotal(vector<vector<int> > triangle)
    {
    //设dp[i][j]为第i行,第j列的最小路径和,从最后一行一直推到第一行
    int n = triangle.size();
    vector<vector<int> > dp(n);
    for (int i = 0; i < triangle[n-1].size(); i++)
    {
    dp[n-1].push_back(triangle[n-1][i]);
    }
    for (int i = n-2; i >= 0; i--)
    {
    for (int j = 0; j < triangle[i].size(); j++)
    {
    if (dp[i+1][j] < dp[i+1][j+1])
    {
    dp[i].push_back(dp[i+1][j] + triangle[i][j]);
    }
    else
    {
    dp[i].push_back(dp[i+1][j+1] + triangle[i][j]);
    }
    }
    }
    return dp[0][0];
    }
    int main()
    {
    vector<int> temp;
    vector<vector<int> > triangle;
    temp.push_back(2);
    triangle.push_back(temp);
    temp.clear();
    temp.push_back(3);
    temp.push_back(4);
    triangle.push_back(temp);
    temp.clear();
    temp.push_back(6);
    temp.push_back(5);
    temp.push_back(7);
    triangle.push_back(temp);
    temp.clear();
    temp.push_back(4);
    temp.push_back(1);
    temp.push_back(8);
    temp.push_back(3);
    triangle.push_back(temp);
    cout << minimumTotal(triangle) << endl;
    system("pause");
    return 0;
    }

  • 相关阅读:
    warning: rpmts_HdrFromFdno: Header V4 DSA/SHA1 Signature, key ID 192a7d7d: NOKEY
    warning: rpmts_HdrFromFdno: Header V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY
    535 5.7.8 Error: authentication failed: generic failure安装EMOS时SMTP测试报错
    mysql-libs版本冲突卸载不了
    history
    CentOS 7 / RHEL 7 运行单用户模式进行root的密码重置
    chkconfig
    Linux主机名域名修改问题
    Mysql正常启动之后默认使用的文件
    解决mysql“Access denied for user 'root'@'localhost'”
  • 原文地址:https://www.cnblogs.com/mengjuanjuan/p/10165389.html
Copyright © 2011-2022 走看看