• 动态规划——《背包问题》


    474. 一和零(两种容量的0-1背包问题)

    在计算机界中,我们总是追求用有限的资源获取最大的收益。

    现在,假设你分别支配着 m 个 0 和 n 个 1。另外,还有一个仅包含 0 和 1 字符串的数组。

    你的任务是使用给定的 m 个 0 和 n 个 1 ,找到能拼出存在于数组中的字符串的最大数量。每个 0 和 1 至多被使用一次。

    状态转移方程:dp[i][j]=(dp[i-s_k_zeros][j-s_k_ones]+1, dp[i][j]);

    int findMaxForm(vector<string>& strs, int m, int n) {
            vector<vector<int>> dp(m+1,vector(n+1,0));
            for(string& s : strs){
                vector<int> cnt = count(s);
                int zeros=cnt[0],ones=cnt[1];
    
                for(int i=m;i>=zeros;i--)
                    for(int j=n;j>=ones;j--){
                        dp[i][j]=max(dp[i-zeros][j-ones]+1,dp[i][j]);
                    }
                }
            return dp[m][n];
        }
        vector<int> count(string& s){
            int z=0,o=0;
            for(int i=0;i<s.length();i++){
                if(s[i]=='0')z++;
                else o++;
            }
            return {z,o};
        }

    494. 目标和 (背包总重可变的固定物品数量的0-1背包问题)

    给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。

    返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

    这道题基本上是自己独立思考想出来的啊哈哈哈哈哈哈

    状态转移方程:dp[i][j]=max(dp[i-1][j-nums[i]]+dp[i-1][j+nums[i]],dp[i][j]);

    int findTargetSumWays(vector<int>& nums, int S) {
            int n=nums.size();
            int low=0,up=0;
            for(int i=0;i<nums.size();i++){
                low-=nums[i];
                up+=nums[i];
            }
            if(S<low||S>up)return 0;
            vector<vector<int>> dp(n,vector<int>(4020,0));
            dp[0][nums[0]+1000]++;dp[0][1000-nums[0]]++;
            for(int i=1;i<n;i++){
                for(int j=S+2000;j>=0;j--){
                    if(j>=nums[i])
                        dp[i][j]=max(dp[i-1][j-nums[i]]+dp[i-1][j+nums[i]],dp[i][j]);
                    else 
                        dp[i][j]=max(dp[i-1][j+nums[i]],dp[i][j]);
                }  
            }
            return dp[n-1][S+1000];
        }

    375. 猜数字大小 II

    我们正在玩一个猜数游戏,游戏规则如下:

    我从 1 到 n 之间选择一个数字,你来猜我选了哪个数字。

    每次你猜错了,我都会告诉你,我选的数字比你的大了或者小了。

    然而,当你猜了数字 x 并且猜错了的时候,你需要支付金额为 x 的现金。直到你猜到我选的数字,你才算赢得了这个游戏

    用动态规划列举猜测的所有情况,每次划分的左右两个区间内,假设正确的数字在代价更大的那个区间,找到有最小代价的划分元素。

    int getMoneyAmount(int n) {
            vector<vector<int>> dp(n+1,vector<int>(n+1,0));
            for(int len=2;len<=n;len++){
                for(int start=1;start<=n-len+1;start++){
                    int mas=INT_MAX;
                    for(int i=start;i<start+len-1;i++){
                        int t=i+max(dp[start][i-1],dp[i+1][start+len-1]);
                        mas=min(mas,t);
                    }
                    dp[start][start+len-1]=mas;
                }
            }
            return dp[1][n];
        }

    待续。。。 

  • 相关阅读:
    2019.10.11CSS
    2019.10.11 THML
    虚拟机FAQ
    thinkpad安装虚拟机 开启虚拟功能要在bios的security里面设置
    JDK在windows系统下环境变量的设置
    有关operamasks-ui的一些信息汇总
    从用List给ArrayList赋值看容器的传值,最好用.addAll
    给eclipse安装svn插件
    Java接口 枚举型Enumeration
    linux下的grep命令
  • 原文地址:https://www.cnblogs.com/Dancing-Fairy/p/12747911.html
Copyright © 2020-2023  润新知