问题描述
小C来到了一家饭馆,这里共有 n 道菜,第 i 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 i 道菜是否含有蘑菇。如果 s_i = '1',那么第 i 道菜含有蘑菇,否则没有。
小C希望点 k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 m 道菜含有蘑菇。小C想知道在满足条件的情况下能选出的最小总价格是多少。如果无法按照要求选择菜品,则输出-1。
问题思路分析
我们需要从给定的菜品中选择 k 道菜,使得总价格最小,并且满足以下条件:
- 菜品中至多只能有 m 道含有蘑菇。
- 如果没有满足条件的选择方案,则返回 -1。
思路分析
-
菜品的描述:
- 每道菜都有价格
a_i和是否含有蘑菇的标志s_i。 s_i = '1'表示该菜品含有蘑菇,s_i = '0'表示该菜品不含蘑菇。
- 每道菜都有价格
-
目标:
- 从所有菜品中选择 k 道菜,使得菜品的总价格尽可能低。
- 在这 k 道菜中,含有蘑菇的菜品数量不能超过 m 道。
-
贪心策略:
- 为了确保选择的总价格最小,我们需要优先选择价格较低的菜品。
- 我们首先根据价格对所有菜品进行排序,确保我们能从价格最低的菜品中选择。
- 接着,我们在选择时,优先选择不含蘑菇的菜品,以避免超出最大蘑菇菜品的限制(
m)。
-
步骤解析:
-
数据结构:
- 将菜品的信息(价格和是否含有蘑菇)存入一个结构体
mm,然后对这些菜品按照价格升序排序。
- 将菜品的信息(价格和是否含有蘑菇)存入一个结构体
-
遍历选择菜品:
- 我们需要在排序后的菜品列表中进行遍历,首先选取不含蘑菇的菜品,如果没有足够的不含蘑菇的菜品,就选择含蘑菇的菜品。每选一个菜,就累计其价格。
-
终止条件:
- 如果我们选择的菜品数目达到了 k,且符合蘑菇数量不超过 m 的条件,返回总价格。
- 如果无法在满足条件的情况下选择到 k 道菜品,则返回 -1。
-
-
边界条件:
- 如果菜品数量
n小于 k,直接返回 -1。 - 如果不可能在 k 道菜品中包含不超过 m 道蘑菇菜品,也返回 -1。
- 如果菜品数量
完整代码
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
struct mm{
int a;
int s;
};
bool cmp(mm a, mm b){
if(a.a==b.a){
return a.s<b.s;
}
return a.a<b.a;
}
long solution(const std::string& s, const std::vector<int>& a, int m, int k) {
// write code here
vector<mm> arr;
for(int i=0;i<s.size();i++)
{
mm v;
int ss=int(s[i])-'0';
v.s=ss;
v.a=a[i];
arr.push_back(v);
}
sort(arr.begin(),arr.end(),cmp);
int ans=0;
long res=0;
int j=0;
while(ans<m&&j<s.size()){
res+=arr[j].a;
if(arr[j].s){
ans++;
}
j++;
if(j>=k)
{
return res;
}
}
int i=j;
int si=j;
while(i<s.size())
{
if(arr[i].s==0){
si++;
res+=arr[i].a;
}
if(si>=k)
{
return res;
}
i++;
}
return -1;
}
int main() {
std::cout << (solution("001", {10, 20, 30}, 1, 2) == 30) << std::endl;
std::cout << (solution("111", {10, 20, 30}, 1, 2) == -1) << std::endl;
std::cout << (solution("0101", {5, 15, 10, 20}, 2, 3) == 30) << std::endl;
std::cout << (solution("100111110010000", {3,4,9,13,16,4,3,9,1,11,7,7,4,4,11}, 1, 4) == 12) << std::endl;
std::cout << solution("100111110010000", {3,4,9,13,16,4,3,9,1,11,7,7,4,4,11}, 1, 4)<< std::endl;
return 0;
}