NO.36 饭馆菜品选择问题
问题描述
小C来到了一家饭馆,这里共有 n 道菜,第 i 道菜的价格为 a_i。其中一些菜中含有蘑菇,s_i 代表第 i 道菜是否含有蘑菇。如果 s_i = '1',那么第 i 道菜含有蘑菇,否则没有。
小C希望点 k 道菜,且希望总价格尽可能低。由于她不喜欢蘑菇,她希望所点的菜中最多只有 m 道菜含有蘑菇。小C想知道在满足条件的情况下能选出的最小总价格是多少。如果无法按照要求选择菜品,则输出-1。
测试样例
样例1:
输入:
s = "001", a = [10, 20, 30], m = 1, k = 2
输出:30
样例2:
输入:
s = "111", a = [10, 20, 30], m = 1, k = 2
输出:-1
样例3:
输入:
s = "0101", a = [5, 15, 10, 20], m = 2, k = 3
输出:30
题目解析
为了实现总价格尽可能低,且含有蘑菇的菜品的数量不超过上限,我们可以先对价格列表进行升序排序,再遍历价格确定要点的菜品。
定义变量如下:
- 目前菜品总价:cost
- 目前已点菜品数量:cnt
- 目前已点含有蘑菇的菜品数量:num
在遍历过程中:
- 当目前所点的菜品数量 cnt 还没达到 k 时,则可以接着点菜。否则,返回目前菜品总价 cost ;
- 当目前所点的含有蘑菇的菜品数量 num 还没达到 m 时,则可以接着点带有蘑菇的菜品。否则,点菜时需要跳过含有蘑菇的菜品。
代码实现
#include <iostream>
#include <vector>
#include <string>
using namespace std;
long solution(const std::string& s, const std::vector<int>& a, int m, int k) {
string S=s; //定义并拷贝s到S
vector<int>A(s.length()); //定义vertor<int>A
A=a; //把a拷贝到A中
//冒泡排序
for(int i=0;i<s.length();i++){
for(int j=i;j<s.length();j++){
if(A[i]>A[j]){
swap(A[i],A[j]); //利用swap交换数值
char ch=S[i]; //借助临时变量ch,交换字符
S[i]=S[j];
S[j]=ch;
}
}
}
int cost = 0; //目前菜品总价
int cnt = 0; //目前已点菜品数量
int num = 0; //目前已点含有蘑菇的菜品数量
for(int i=0;i<s.length();i++){
if(cnt==k) return cost; //若遍历结束前已点满菜品,则返回cost
if(S[i]=='0' && cnt<k){
cnt++;
cost += A[i];
}else if(S[i] == '1' && num < m){ //若这道菜含有蘑菇,且有蘑菇的菜品数量num小于最大值m,则这道菜加入已点菜品
cnt++;
cost += A[i];
num++;
}else if(S[i] == '1' && num == m){
continue; //若目前所点的含有蘑菇的菜品数量num已达m,且这道菜含有蘑菇,则跳过这道菜,看下一道菜
}
}
if(cnt==k) return cost; //菜品点满,符合题意,返回cost
if(cnt<k) return -1; //菜品不足,不符题意,返回-1
}
注意:
- 由于原始状态下,s 和 a 在同一位置下的数值是一一对应的,即 s[i] 和 a[i] 意味着第 i 道菜是否含有蘑菇以及第 i 道菜的价格,故对 a[i] 根据价格高低进行升序排序的时候,需要同步对 s[i] 调整排序。
- 由于传入函数 solution(const std::string& s, const std::vector& a, int m, int k) 的参数 s 和 a 都是const类型,但我们需要对其进行排序,故新定义一个string类型的变量 S ,用来拷贝 s 的初始值,新定义一个vector类型的变量 A,用来拷贝 a 的初始值,并进行排序。