zoukankan      html  css  js  c++  java
  • dp总结篇

    dp,直接递推和记忆化搜索

    leetcode 1553 吃掉N个橘子的最少天数

    思路:除2或除3总比减一划算,所以先减掉余数再除。由于N很大,需要记忆化搜索;由于N很大,不能用数组,可以用unordered_map

    class Solution {
    public:
        // vector<int>dp;
        unordered_map<int, int>mp;
        int dfs(int n) {
            if(mp[n])  return mp[n];
            int& ans = mp[n];
            if(n == 0)  return ans=-1;  // 特殊,1需要1次,0最小需要-1次
            return ans = min(dfs(n/3)+n%3, dfs(n/2)+n%2)+1;
        }
        int minDays(int n) {
            // dp.resize(n+1, -1);
            return dfs(n);
        }
    };
    View Code

    leetcode 902 最大为N的数组组合

    思路:数位dp,逐位考虑,同时记录前面的一些必要信息。pre记录是否已经小于,flag记录前面是否是全0. (细节挺多,每种情况都要考虑到,到最后发现很多情况能合并)

    class Solution {
    public:
        typedef long long  ll;
        ll qpow(ll a, ll b) {
            ll ret = 1;
            while(b) {
                if(b&1) ret *= a;
                b >>= 1;
                a *= a;
            }
            return  ret;
        }
        ll dfs(vector<string>& digits, vector<int>& limits, int pos, bool pre, bool flag) { // 
            // cout << "pos: " << pos << endl;
            int n = digits.size(), m = limits.size();
            if(pos >= m)  return !flag;
            int limit = limits[pos];
            ll ret = 0;
            // 前面小
            if(pre)
            {
                // 填0
                if(flag)  ret += dfs(digits, limits, pos+1, pre, flag);
                // 不填0
                ret += qpow(n, m-pos);
            } else { // 前面等
                int i = 0;
                for(;i < n;i++)
                    if(stoi(digits[i]) >= limit)  break;
    
                // 填limit
                if(i < n && stoi(digits[i]) == limit)  ret += dfs(digits, limits, pos+1, pre, false);
                // 填0
                if(flag)  ret += dfs(digits, limits, pos+1, true, flag);
                // 填(0, limit)
                ret += i*qpow(n, m-pos-1);
            }
        
            return ret;
        }
        int atMostNGivenDigitSet(vector<string>& digits, int n) {
            int tmp = n;
            vector<int>limits;
            while(tmp) {
                limits.insert(limits.begin(), tmp%10);
                tmp /= 10;
            }
    
            // for(int num : limits)  cout << num << " ";
            ll ans = dfs(digits, limits, 0, false, true);
    
            return ans;
        }
    };
    View Code
    个性签名:时间会解决一切
  • 相关阅读:
    一个将配置文件转换成xml的示例程序
    DatagridView控件加CheckBox
    Sql Server Split函数
    SQL语句压缩数据库和Log
    NPOI、OpenXML SDK、OpenOffice SDK 操作Excel
    判断参数对象是否为DBNULL
    软件开发模型
    c# ComboBox禁用鼠标滚轮
    动态管理视图和函数的使用
    TreeView 在失去焦点的时候 选中的TreeNode仍为高亮
  • 原文地址:https://www.cnblogs.com/lfri/p/14578841.html
Copyright © 2011-2022 走看看