LC638-大礼包

638. 大礼包

完全背包 + 状压 + 记忆化搜索

class Solution {
public:
    vector<vector<int>>special;
    vector<unordered_map<int, int>> f;
    vector<int>price;
    int n;
    int dp(int x, int y){
        if(f[x].count(y)) return f[x][y];
        if(!x){
            f[x][y] = 0;
            for(int i = n - 1; i >= 0; --i){
                int c = y >> i * 4 & 15;   // 取16进制位数
                f[x][y] += c * price[i];
            }
            return f[x][y];
        } 
        f[x][y] = dp(x - 1, y);
        int v = 0;
        for(int j = n - 1; j >= 0; --j){
            int c = y >> j * 4 & 15;
            if(c < special[x - 1][j]){
                v = -1;
                break;
            }
            v = v * 16 + c - special[x - 1][j];
        }
        if(~v)f[x][y] = min(f[x][y], dp(x, v) + special[x - 1].back());
        return f[x][y];
    }
    int shoppingOffers(vector<int>& _price, vector<vector<int>>& _special, vector<int>& needs) {
        //直接完全背包状态数过多,利用记忆化搜索解决(可以省去一些对结果无法无意义的状态)
        price = _price, special = _special;
        n = price.size();
        int state = 0;
        f = vector<unordered_map<int, int>>(special.size() + 1,  unordered_map<int, int>());//状压成16进制数,用哈希表减少状态数
        for(int i = needs.size() - 1; i >= 0; --i) state = state * 16 + needs[i];
        return dp(special.size(), state);
    }
};
上一篇:学习python的类


下一篇:xlwings 使用总结