美文网首页
动态规划

动态规划

作者: CristianoC | 来源:发表于2020-08-26 21:38 被阅读0次

    动态规划分为三步:定义数组元素含义,找到初始值,写状态转移方程,做多基本就没啥问题了,当然都会做之后还涉及到一个优化问题。

    1. 最大序列和
    #include <iostream>
    using namespace std;
    const int maxn = 1000000;
    //定义d[i]为从0到i最大序列和
    int main(){
        int n;
        while (cin>>n){
            int dp[maxn],a[maxn];
            for(int i = 0;i < n;i++)
                cin>>a[i];
            dp[0] = a[0];
            int sum = a[0];
            for(int i = 1;i < n;i++){
                dp[i] = max(dp[i-1] + a[i],a[i]);
                if(sum < dp[i])
                    sum = dp[i];
            }
            cout<<sum<<endl;
        }
        return 0;
    }
    

    最长上升子序列 判断在某个数前面是不是有比他小的数

    #include <iostream>
    #include <memory.h>
    using namespace std;
    const int maxn = 1005;
    int main(){
        int n;
        while (cin>>n){
            int dp[maxn],number[maxn];
            for(int i = 0;i < n;i++){
                cin>>number[i];
            }
            for(int i = 0;i < n;i++)
                dp[i] = number[i];
            int ans = 0;
            for(int i = 0;i < n;i++){
                for(int j = 0;j < i;j++){
                    if(number[j] < number[i])
                        dp[i] = max(dp[j] + number[i],dp[i]);
                }
                ans = max(ans,dp[i]);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    

    最大公共子序列 注意循环的起始和判断的条件 注意区分开最长公共子串(前一字母相同的情况一样,但是如果不同则归0,即dp[i][j] = 0)

    #include <iostream>
    #include <memory.h>
    using namespace std;
    const int maxn = 105;
    int main(){
        string a,b;
        while (cin>>a>>b) {
            int dp[maxn][maxn];
            int len_a = a.length();
            int len_b = b.length();
            memset(dp, 0, sizeof(dp));
            for(int i = 1;i <= len_a;i++){
                for(int j = 1;j <= len_b;j++){
                    if(a[i-1] == b[j-1])
                        dp[i][j] = dp[i-1][j-1] + 1;
                    else
                        dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
                }
            }
            cout<<dp[len_a][len_b]<<endl;
        }
        return 0;
    }
    
    1. 背包问题
      分为三种类似,01背包,完全背包、多重背包,掌握好状态转移方程即可。
    #include <iostream>
    #include <memory.h>
    using namespace std;
    //0 1背包 这里注意有一个优化的地方就是将状态转移方程降维 因为每一个状态都仅仅对前一行状态有关
    int main(){
        int n,w;
        while (cin>>w>>n){
            int weight[n],dp[w];
            for(int i = 1;i <= n;i++)
                cin>>weight[i];
            memset(dp,0, sizeof(dp));
            for(int i = 1;i <= n;i++) {
                for (int j = w; j >=  weight[i]; j--) {
                        dp[j] = max(dp[j], dp[j - weight[i]] + weight[i]);
                }
            }
                if (dp[w] == w)
                    cout << "YES" << endl;
                else
                    cout << "NO" << endl;
    
        }
        return 0;
    }
    
    #include <iostream>
    #include <memory.h>
    using namespace std;
    //完全背包 注意好优化的时候要正序
    int main(){
        int n,w;
        while (cin>>n>>w){
            int weight[n],value[n];
            int dp[w];
            memset(dp,0, sizeof(dp));
            for(int i = 1;i <= n;i++)
                cin>>weight[i]>>value[i];
            for(int i = 1;i <= n;i++){
                for(int j = weight[i];j <= w;j++){
                        dp[j] = max(dp[j],dp[j - weight[i]] + value[i]);
                }
            }
            cout<<dp[w]<<endl;
        }
        return 0;
    }
    

    如果是问有多少种方案的话,就是把方程从max改成+,然后取消+value[i]

    #include <iostream>
    #include <memory.h>
    using namespace std;
    const int maxn = 10005;
    int main(){
        int n;
        while (cin>>n){
            int weight[maxn];
            for(int i = 1;i <= n;i++)
                cin>>weight[i];
            int dp[maxn];
            memset(dp,0, sizeof(dp));
            dp[0] = 1;
            for(int i = 1;i <= n;i++){
                for(int j = 40;j >= weight[i];j--)
                    dp[j] = dp[j] + dp[j - weight[i]];
            }
            cout<<dp[40]<<endl;
        }
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:动态规划

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