Leetcode_638.Shopping Offers
https://leetcode.com/problems/shopping-offers/
In LeetCode Store, there are some kinds of items to sell. Each item has a price.
However, there are some special offers, and a special offer consists of one or more different kinds of items with a sale price.
You are given the each item's price, a set of special offers, and the number we need to buy for each item. The job is to output the lowest price you have to pay for exactly certain items as given, where you could make optimal use of the special offers.
Each special offer is represented in the form of an array, the last number represents the price you need to pay for this special offer, other numbers represents how many specific items you could get if you buy this offer.
You could use any of special offers as many times as you want.
Example 1:
Input: [2,5], [[3,0,5],[1,2,10]], [3,2]
Output: 14
Explanation:
There are two kinds of items, A and B. Their prices are $2 and $5 respectively.
In special offer 1, you can pay $5 for 3A and 0B
In special offer 2, you can pay $10 for 1A and 2B.
You need to buy 3A and 2B, so you may pay $10 for 1A and 2B (special offer #2), and $4 for 2A.
Example 2:
Input: [2,3,4], [[1,1,0,4],[2,2,1,9]], [1,2,1]
Output: 11
Explanation:
The price of A is $2, and $3 for B, $4 for C.
You may pay $4 for 1A and 1B, and $9 for 2A ,2B and 1C.
You need to buy 1A ,2B and 1C, so you may pay $4 for 1A and 1B (special offer #1), and $3 for 1B, $4 for 1C.
You cannot add more items, though only $9 for 2A ,2B and 1C.
Note:
- There are at most 6 kinds of items, 100 special offers.
- For each item, you need to buy at most 6 of them.
- You are not allowed to buy more items than you want, even if that would lower the overall price.
1.最多6种物品,每种最多买6个。所以一开始想到的是,用一个整数的每一位来表示一种物品买了多少个,dp[666666]表示6种物品每种买6个。这样可以将问题转化为一个完全背包问题。
struct Item
{
int val,cost;
Item(int v,int c):val(v),cost(c) {}
bool operator < (const Item& item)const
{
return item.cost>cost;
}
};
class Solution
{
public:
bool legal(int x)
{
while(x>)
{
if(x%>)
return ;
x/=;
}
return ;
}
bool bigger(int a, int b)
{
while(a>&&b>)
{
if(a% < b%)
return ;
a/=;
b/=;
}
if(a>)
return ;
else if(a== && b==)
return ;
else
return ;
}
int shoppingOffers(vector<int>& price, vector<vector<int>>& special, vector<int>& needs)
{
int all=;
for(int i=,w=; i<needs.size(); i++,w*=)
all += needs[i]*w;
vector<int> dp(all+,INT_MAX/);
dp[]=;
vector<Item> items;
for(int i=,w=; i<price.size(); i++,w*=)
items.push_back(Item(price[i], w));
for(int i=; i<special.size(); i++)
{
int cost=;
for(int j=,w=; j<special[i].size()-; j++,w*=)
cost += special[i][j]*w;
items.push_back(Item(special[i][special[i].size()-], cost));
}
for(int i=; i<items.size(); i++)
for(int j=items[i].cost; j<=all; j++)
if(legal(j) && bigger(j,j-items[i].cost))
{
dp[j] = min(dp[j], dp[j-items[i].cost] + items[i].val);
//cout<<dp[j]<<endl;
}
return dp[all];
}
};
DP
但是发现这样做的问题在于状态数最多有666666个,只用背包的解法复杂度很高,虽然过了,但是耗时2000ms,且使用70+Mb的内存空间。
2.第二种解法是用dfs,这里使用类似向量的运算来处理special,price和needs,重载运算符后很方便且可读性高。并且,dfs搜索的状态数远小于前一种解法。
bool operator < (const vector<int>& v, const int x)
{
for(auto& i:v)
if(i<x)
return true;
return false;
} bool operator <= (const vector<int>& v1, const vector<int>& v2)
{
for(int i=; i<v2.size(); i++)
if(v1[i]>v2[i])
return false;
return true;
} int operator * (const vector<int>& v1, const vector<int>& v2)
{
int ret=;
for(int i=; i<v1.size(); i++)
ret += v1[i] * v2[i];
return ret;
} vector<int> operator -= (vector<int>& v1, const vector<int>& v2)
{
for(int i=; i<v1.size(); i++)
v1[i] -= v2[i];
return v1;
} vector<int> operator += (vector<int>& v1, const vector<int>& v2)
{
for(int i=; i<v1.size(); i++)
v1[i] += v2[i];
return v1;
} class Solution
{
public:
int shoppingOffers(vector<int>& price, vector<vector<int> >& special, vector<int>& needs, int cost=)
{
if(needs < )
return INT_MAX;
int ret = cost + price * needs;
for(int i=; i<special.size(); i++)
{
if(special[i] <= needs)
{
needs -= special[i];
ret = min(ret, shoppingOffers(price, special, needs, cost+special[i].back()));
needs += special[i];
}
}
return ret;
}
};
dfs
这种解法耗时8ms,使用不到10Mb的空间。
Leetcode_638.Shopping Offers的更多相关文章
- 洛谷P2732 商店购物 Shopping Offers
P2732 商店购物 Shopping Offers 23通过 41提交 题目提供者该用户不存在 标签USACO 难度提高+/省选- 提交 讨论 题解 最新讨论 暂时没有讨论 题目背景 在商店中, ...
- poj 1170 Shopping Offers
Shopping Offers Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 4696 Accepted: 1967 D ...
- USACO 3.3 Shopping Offers
Shopping OffersIOI'95 In a certain shop, each kind of product has an integer price. For example, the ...
- LeetCode 638 Shopping Offers
题目链接: LeetCode 638 Shopping Offers 题解 dynamic programing 需要用到进制转换来表示状态,或者可以直接用一个vector来保存状态. 代码 1.未优 ...
- HDU 1170 Shopping Offers 离散+状态压缩+完全背包
题目链接: http://poj.org/problem?id=1170 Shopping Offers Time Limit: 1000MSMemory Limit: 10000K 问题描述 In ...
- 背包系列练习及总结(hud 2602 && hdu 2844 Coins && hdu 2159 && poj 1170 Shopping Offers && hdu 3092 Least common multiple && poj 1015 Jury Compromise)
作为一个oier,以及大学acm党背包是必不可少的一部分.好久没做背包类动规了.久违地练习下-.- dd__engi的背包九讲:http://love-oriented.com/pack/ 鸣谢htt ...
- Leetcode之深度优先搜索&回溯专题-638. 大礼包(Shopping Offers)
Leetcode之深度优先搜索&回溯专题-638. 大礼包(Shopping Offers) 深度优先搜索的解题详细介绍,点击 在LeetCode商店中, 有许多在售的物品. 然而,也有一些大 ...
- LC 638. Shopping Offers
In LeetCode Store, there are some kinds of items to sell. Each item has a price. However, there are ...
- Week 9 - 638.Shopping Offers - Medium
638.Shopping Offers - Medium In LeetCode Store, there are some kinds of items to sell. Each item has ...
随机推荐
- Navicat 提示Cannot create oci environment 解决方案
一直在使用 Navicat ,这是一个数据库客户端软件,能连接多种不同类型的数据库,给我们的日常的工作带来了不少的便捷.当Navicat 就莫名其妙的不能连接 oracle 数据库了.总是提示如下错误 ...
- XMU 1071 圣斗士黄金十二宫(七)银河星爆 【计算几何】
1071: 圣斗士黄金十二宫(七)银河星爆 Time Limit: 500 MS Memory Limit: 64 MBSubmit: 193 Solved: 10[Submit][Status] ...
- Oracle - 数据更新 - 增删改
/* 数据的更新 增加 删除 修改 */ -----------------------------------增加(一次只能插入一条数据) --自定义插入数据列的顺序 ,,); --按照数据库默认的 ...
- UVA10600 ACM Contest and Blackout —— 次小生成树
题目链接:https://vjudge.net/problem/UVA-10600 In order to prepare the “The First National ACM School Con ...
- python-----用多张图片生成视频
代码如下 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019/2/19 16:42 # @Author : xiaodai # - ...
- c#截图工具
厚积薄发,丰富的公用类库积累,助你高效进行系统开发(6)----全屏截图.图标获取.图片打印.页面预览截屏.图片复杂操作等 俗话说,一个好汉十个帮,众人拾柴火焰高等都说明一个道理,有更多的资源,更丰富 ...
- 去除inline-block的间隙
产生间隙的原因就是标签之间的空格,去除的方法: 1 设置父元素的font-size:0;空格字符的宽高都为0, <div class="demo1 demo2"> &l ...
- vue2.0构建单页应用最佳实战
链接: https://www.tuicool.com/articles/me6RJfF
- bzoj 3308: 九月的咖啡店【最大费用最大流】
费用流里spfa最后的判断要写成dis[t]>=0而不是dis[t]!=-inf否则会WAWAWA-- #include<iostream> #include<cstdio&g ...
- [POI2008]BLO-Blockade 【无向图tarjan/鸽点】By cellur925
题目传送门 lyd无向图tarjan的例题. 一句话题意(不得不佩服lyd老师的高度概括能力):在一张无向连通图上,求出每个点被破坏(去掉与这个点相关的所有边,不去掉这个点)后,无向图中使i,j不连通 ...