栈
1:编程语言中函数的调用
2:操作系统中从用户态到内核寄存器的保存
3:网络消息的处理。
- demo1:20. 有效的括号 - 力扣(LeetCode)
class Solution
{
public:
bool isValid(string s)
{
std::map<char, char> map = {
{'(', ')'},
{'[', ']'},
{'{', '}'}};
stack<char> stack;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == '(' || s[i] == '[' || s[i] == '{')
{
stack.push(s[i]);
}
else if (!stack.empty() && s[i] == map[stack.top()])
{
stack.pop();
}
else
{
return false;
}
}
return stack.empty();
}
};
class Solution:
def isValid(self, s):
dic = {'{': '}', '[': ']', '(': ')'} # 定义字典
stack = []
for c in s:
if c in dic:
stack.append(c)
elif len(stack) != 0 and dic[stack[-1]] == c:
stack.pop()
else:
return False
return len(stack) == 0
- demo2:
int solution(vector<int> size, vector<int> dir)
{
stack<int> stack;
stack.push(dir[0]);
for (int i = 1; i < dir.size(); i++)
{
if (dir[i] == stack.top()) // 符号相同入栈
{
stack.push(dir[i]);
}
else
{
while (dir[i] == 0 && stack.top() == 1) // 符号不相同,
{
if (size[stack.top()] > size[i]) // 栈中元素大
{
break;
}
else
{ // 栈中元素小,移除,如果栈大小为0,退出
stack.pop();
if (stack.empty())
{
stack.push(dir[i]);
break;
}
}
}
}
}
return stack.size();
};
- demo3
vector<int> FindRightSmall(vector<int> vec)
{
stack<int> stack; // 单调递增栈
vector<int> ret(vec.size());
stack.push(0);
for (int i = 1; i < vec.size(); i++)
{
if (vec[stack.top()] < vec[i]) // 当前元素大
{
stack.push(i);
}
else
{
while (!stack.empty() && vec[stack.top()] > vec[i]) // 当前元素小了,找到目标元素
{
ret[stack.top()] = i;
stack.pop();
}
stack.push(i);
}
}
while (!stack.empty())
{
ret[stack.top()] = -1;
stack.pop();
}
return ret;
}
def FindRightSmall(vec):
stack = []
ret = [-1] * len(vec)
stack.append(0)
for iter in range(1, len(vec)):
if (vec[stack[-1]] < vec[iter]):
stack.append(iter)
else:
while (len(stack) != 0 and vec[stack[-1]] > vec[iter]):
ret[stack[-1]] = iter
stack.pop()
stack.append(iter)
while (len(stack) != 0):
ret[stack[-1]] = -1
stack.pop()
return ret
- demo4
vector<int> FindSmallNumber(vector<int> vec, int k)
{
stack<int> stack; // 单调递增栈
vector<int> ret(k);
stack.push(0);
for (int i = 1; i < vec.size(); i++)
{
if (vec[stack.top()] < vec[i]) // 如果右边的数大,放入
{
stack.push(i);
}
else
{
while (!stack.empty() && vec[stack.top()] > vec[i] && (stack.size() + vec.size() - i) > k) // 栈的个数加上剩余的元素大于k
{
stack.pop();
}
stack.push(i);
}
};
while (stack.size() > k)
{
stack.pop();
}
for (int i = k - 1; i >= 0; i--)
{
ret[i] = vec[stack.top()];
stack.pop();
}
return ret;
}
def FindSmallNumber(vec, k):
stack = []
ret = [0] * k
stack.append(0)
for iter in range(1, len(vec)):
if (vec[stack[-1]] < vec[iter]):
stack.append(iter)
else:
while (len(stack) != 0 and vec[stack[-1]] > vec[iter] and (len(stack) + len(vec)-iter > k)):
stack.pop()
stack.append(iter)
while (len(stack) > k):
stack.pop()
for iter in range(k-1, -1, -1):
ret[iter] = vec[stack[-1]]
stack.pop()
return ret
队列
- demo1
// 队列遍历
class Solution
{
public:
vector<vector<int>> levelOrder(TreeNode *root)
{
if (root == nullptr)
{
return vector<vector<int>>();
}
vector<vector<int>> ret;
vector<int> ret_index;
queue<TreeNode *> que;
que.push(root);
while (!que.empty())
{
int size = que.size();
for (int i = 0; i < size; i++)
{
TreeNode *cur = que.front();
ret_index.push_back(cur->val);
que.pop();
if (cur->left != nullptr)
{
que.push(cur->left);
}
if (cur->right != nullptr)
{
que.push(cur->right);
}
}
ret.push_back(ret_index);
ret_index.clear();
}
return ret;
}
};
// 顺序遍历
// vector遍历
class Solution
{
public:
vector<vector<int>> levelOrder(TreeNode *root)
{
if (root == nullptr)
{
return vector<vector<int>>();
}
vector<vector<int>> ret;
vector<int> ret_index;
vector<TreeNode *> cur_level;
vector<TreeNode *> next_level;
if (root != nullptr)
{
cur_level.push_back(root);
}
while (!cur_level.empty())
{
for (auto iter : cur_level)
{
ret_index.push_back(iter->val);
if (iter->left != nullptr)
{
next_level.push_back(iter->left);
};
if (iter->right != nullptr)
{
next_level.push_back(iter->right);
};
}
ret.push_back(ret_index);
ret_index.clear();
cur_level = next_level;
next_level.clear();
}
return ret;
}
};
- demo2
// 循环队列
// 放入元素rear+1,删除元素front+1
//[)
class MyCircularQueue
{
private:
vector<int> que;
int front = 0;
int rear = 0;
public:
MyCircularQueue(int k)
{
que.resize(k + 1);
};
bool enQueue(int value)
{
if (!isFull())
{
// 把元素放到rear位置
que[rear] = value;
// rear向后移动
rear = (rear + 1) % que.size();
return true;
}
else
{
return false;
}
};
// 出队,不删除元素
bool deQueue()
{
if (isEmpty())
{
return false;
}
else
{
front = (front + 1) % que.size();
return true;
}
};
int Front()
{
return isEmpty() ? -1 : que[front];
};
int Rear()
{
int tail = (rear + que.size() - 1) % que.size();
return isEmpty() ? -1 : que[tail];
};
bool isEmpty()
{
return rear == front;
};
bool isFull()
{
return (rear + 1) % que.size() == front;
};
};
- demo3
// 非严格单调递减双端队列
class Solution
{
private:
deque<int> que;
vector<int> vec;
private:
void DecreasingQueue(int index)
{
while (!que.empty() && vec[que.back()] <= vec[index])
{
que.pop_back();
}
que.push_back(index);
}
public:
vector<int> maxSlidingWindow(vector<int> &nums, int k)
{
vector<int> ret;
// 单调递减队列
vec = nums;
for (int i = 0; i < k; i++)
{
DecreasingQueue(i);
}
ret.push_back(nums[que.front()]);
for (int i = k; i < nums.size(); i++)
{
DecreasingQueue(i);
// 第一个元素超过限制
if (i - que.front() >= k)
{
que.pop_front();
}
ret.push_back(nums[que.front()]);
};
return ret;
}
};
- demo 4
class Solution
{
public:
int maxResult(vector<int> &nums, int k)
{
// 注意大根堆 pair 默认按 first排序
std::priority_queue<pair<int, int>> prior_que; // 默认大根堆,小根堆 + std::greater<>
prior_que.emplace(nums[0], 0);
int ans = nums[0];
for (int i = 1; i < nums.size(); i++)
{
// 为什么不用if 用 while
// 新值会把旧值后移
// 新值pop之后,旧值也必须pop
while (i - prior_que.top().second > k)
{
prior_que.pop();
}
// 这里为什么要定义 prior_que.top().first
// 因为必须要到达最后一个位置,最后一个值可能为负数
ans = prior_que.top().first + nums[i];
prior_que.push(make_pair(ans, i));
}
return ans;
}
};
优先级队列
class Solution
{
public:
vector<int> inventoryManagement(vector<int> &stock, int cnt)
{
vector<int> ret;
ret.resize(cnt);
priority_queue<int, vector<int>, greater<int>>
small_que;
for (int i = 0; i < stock.size(); i++)
{
small_que.emplace(stock[i]);
}
while (cnt--)
{
ret[cnt] = small_que.top();
small_que.pop();
}
return ret;
}
};
class Solution
{
public:
vector<int> topKFrequent(vector<int> &nums, int k)
{
vector<int> ret;
auto iter = [](pair<int, int> a, pair<int, int> b) -> bool
{
return a.second < b.second; // 大堆
};
priority_queue<pair<int, int>, vector<pair<int, int>>, function<bool(pair<int, int>, pair<int, int>)>> greater_queue(iter);
unordered_map<int, int> temp_map;
for (int i = 0; i < nums.size(); i++)
{
temp_map[nums[i]]++;
}
for (auto iter : temp_map)
{
greater_queue.push(iter);
}
while (k--)
{
ret.emplace_back(greater_queue.top().first);
greater_queue.pop();
}
return ret;
}
};
链表
struct ListNode
{
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
// 构造虚拟节点实现链表反转
// 链表的题多画图
class Solution
{
public:
ListNode *reverseList(ListNode *head)
{
ListNode *dummy_node = new ListNode();
while (head != nullptr)
{
// update
ListNode *temp = head->next;
head->next = dummy_node->next;
dummy_node->next = head;
// update
head = temp;
}
return dummy_node->next;
}
};
class Solution
{
public:
ListNode *deleteNode(ListNode *head, int val)
{
ListNode *dummy_list = new ListNode();
ListNode *ret = dummy_list;
while (head)
{
if (head->val != val)
{
dummy_list->next = head;
dummy_list = dummy_list->next;
}
head = head->next;
}
dummy_list->next = nullptr;
return ret->next;
}
};
demo3 83. 删除排序链表中的重复元素 - 力扣(LeetCode)
class Solution
{
public:
ListNode *deleteDuplicates(ListNode *head)
{
ListNode *dummy_list = new ListNode();
ListNode *ret = dummy_list;
// 如何处理头节点? dummy_list == ret
while (head)
{
if (dummy_list == ret || dummy_list->val != head->val)
{
dummy_list->next = head;
dummy_list = dummy_list->next;
}
head = head->next;
}
dummy_list->next = nullptr;
return ret->next;
}
};
demo421. 合并两个有序链表 - 力扣(LeetCode)
class Solution
{
public:
ListNode *mergeTwoLists(ListNode *list1, ListNode *list2)
{
ListNode *dummy_list = new ListNode();
ListNode *ret = dummy_list;
while (list1 != nullptr && list2 != nullptr)
{
if (list1->val <= list2->val)
{
dummy_list->next = list1;
list1 = list1->next;
}
else
{
dummy_list->next = list2;
list2 = list2->next;
}
dummy_list = dummy_list->next;
}
if (list1 != nullptr)
{
dummy_list->next = list1;
}
if (list2 != nullptr)
{
dummy_list->next = list2;
}
return ret->next;
}
};
demo523. 合并 K 个升序链表 - 力扣(LeetCode)
// 常规方法
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* list1_new = new ListNode(0);
ListNode* list_head = list1_new;
while (list1 != nullptr && list2 != nullptr) {
if (list1->val <= list2->val) {
list1_new->next = list1;
list1 = list1->next;
}
else {
list1_new->next = list2;
list2 = list2->next;
}
list1_new = list1_new->next;
}
if (list1 != nullptr) {
list1_new->next = list1;
}
else {
list1_new->next = list2;
}
return list_head->next;
}
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if (lists.size() == 0) {
return nullptr;
}
ListNode* list_nodee = nullptr;
for (int i = 0; i < lists.size(); i++)
{
ListNode* list_node = mergeTwoLists(list_nodee,lists[i]);
list_nodee = list_node;
}
return list_nodee;
}
};
// 小根堆
class Solution
{
private:
public:
ListNode *
mergeKLists(vector<ListNode *> &lists)
{
priority_queue<ListNode *, vector<ListNode *>, function<bool(ListNode *, ListNode *)>> small_que(
[](ListNode *a, ListNode *b) -> bool
{
return a->val > b->val;
});
ListNode *dummy_list = new ListNode();
ListNode *ret = dummy_list;
for (auto iter : lists)
{
if (iter != nullptr)
{
small_que.push(iter);
}
}
while (!small_que.empty())
{
ListNode *smaller = small_que.top();
small_que.pop();
// 更新结果
dummy_list->next = smaller;
dummy_list = dummy_list->next;
// 更新小根堆
if (smaller->next)
{
small_que.push(smaller->next);
}
}
dummy_list->next = nullptr;
return ret->next;
}
};
demo619. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
class Solution
{
public:
ListNode *removeNthFromEnd(ListNode *head, int n)
{
ListNode *dummy_list = new ListNode();
dummy_list->next = head;
ListNode *ret = dummy_list;
ListNode *fast = dummy_list;
int temp = n + 1;
while (fast && temp--)
{
fast = fast->next;
}
while (dummy_list && fast)
{
fast = fast->next;
dummy_list = dummy_list->next;
}
if (dummy_list && dummy_list->next)
{
dummy_list->next = dummy_list->next->next;
}
else
{
dummy_list->next = nullptr;
}
return ret->next;
}
};
树
demo1144. 二叉树的前序遍历 - 力扣(LeetCode)
// 递归
class Solution
{
vector<int> res;
public:
vector<int> preorderTraversal(TreeNode *root)
{
preorder(root);
return res;
}
private:
void preorder(TreeNode *root)
{
if (root == nullptr)
{
return;
}
res.push_back(root->val);
preorder(root->left);
preorder(root->right);
}
};
// 栈
class Solution
{
vector<int> res;
public:
vector<int> preorderTraversal(TreeNode *root)
{
stack<TreeNode *> stack;
if (root == nullptr)
{
return res;
}
stack.push(root);
while (!stack.empty())
{
TreeNode *cur = stack.top();
res.push_back(cur->val);
stack.pop();
if (cur->right)
{
stack.push(cur->right);
}
if (cur->left)
{
stack.push(cur->left);
}
}
return res;
}
};
demo298. 验证二叉搜索树 - 力扣(LeetCode)
// 递归
class Solution
{
void preOrder(TreeNode *root, pair<int64_t, int64_t> section, bool &res)
{
if (!root || !res)
{
return;
}
if (section.first >= root->val || root->val >= section.second)
{
res = false;
return;
}
preOrder(root->left, {section.first, root->val}, res);
preOrder(root->right, {root->val, section.second}, res);
}
public:
bool isValidBST(TreeNode *root)
{
bool res = true;
preOrder(root, {INT64_MIN, INT64_MAX}, res);
return res;
}
};
// 栈
class Solution
{
public:
bool isValidBST(TreeNode *root)
{
stack<pair<TreeNode *, pair<int64_t, int64_t>>> stack;
pair<int64_t, int64_t> section{INT64_MIN, INT64_MAX};
if (root == nullptr)
{
return false;
}
stack.push(make_pair(root, section));
while (!stack.empty())
{
auto iter = stack.top();
TreeNode *cur = iter.first;
pair<int64_t, int64_t> cur_section = iter.second;
stack.pop();
if (!(cur_section.first < cur->val && cur->val < cur_section.second))
{
return false;
}
if (cur->right)
{
stack.push(make_pair(cur->right, make_pair(cur->val, cur_section.second)));
}
if (cur->left)
{
stack.push(make_pair(cur->left, make_pair(cur_section.first, cur->val)));
}
}
return true;
}
};
demo3113. 路径总和 II - 力扣(LeetCode)
class Solution
{
public:
void back_track(TreeNode *node, vector<vector<int>> &res, vector<int> &res_index, int &targetsum)
{
if (!node)
{
return;
}
res_index.push_back(node->val);
int sum = std::accumulate(res_index.begin(), res_index.end(), 0);
if (!node->left && !node->right && targetsum == sum)
{
res.push_back(res_index);
}
back_track(node->left, res, res_index, targetsum);
back_track(node->right, res, res_index, targetsum);
// 回溯
res_index.pop_back();
}
vector<vector<int>> pathSum(TreeNode *root, int targetSum)
{
vector<vector<int>> res;
vector<int> res_index;
back_track(root, res, res_index, targetSum);
return res;
}
};
数组
class Solution
{
public:
int search(vector<int> &nums, int target)
{
int left = 0;
int right = nums.size() - 1;
while (left <= right)
{
int middle = left + (right - left) / 2;
if (nums[middle] == target)
{
return middle;
}
else if (nums[middle] < target)
{
left = middle + 1;
}
else
{
right = middle - 1;
}
}
return -1;
}
};
// 注意二分查找[left,right] 左闭右闭区间
// 区间迭代 middle
class Solution
{
public:
int removeElement(vector<int> &nums, int val)
{
int slow = 0;
for (int fast = 0; fast < nums.size(); fast++)
{
if (nums[fast] != val)
{
nums[slow++] = nums[fast];
}
}
nums.resize(slow);
return slow;
}
};
// 双指针
class Solution
{
public:
vector<int> sortedSquares(vector<int> &nums)
{
int index = nums.size() - 1;
vector<int> res(nums.size());
int left = 0;
int right = nums.size() - 1;
while (left <= right)
{
if (nums[left] * nums[left] > nums[right] * nums[right])
{
res[index--] = nums[left] * nums[left];
left++;
}
else
{
res[index--] = nums[right] * nums[right];
right--;
}
}
return res;
}
};
// 滑动窗口
class Solution
{
public:
int minSubArrayLen(int target, vector<int> &nums)
{
int min = INT_MAX;
int left = 0;
int sum = 0;
for (int right = 0; right < nums.size(); right++)
{
sum += nums[right];
while (sum >= target)
{
min = std::min(min, right - left + 1); // 满足要求,left++
sum -= nums[left++];
}
}
return min == INT_MAX ? 0 : min;
}
};
class Solution
{
public:
vector<vector<int>> generateMatrix(int n)
{
vector<vector<int>> res(n, vector<int>(n));
int left = 0;
int right = n - 1;
int up = 0;
int down = n - 1;
int num = 0;
while (num != n * n)
{
// 上边 左 -> 右
for (int i = left; i <= right; i++)
{
res[up][i] = ++num;
}
up++;
// 右边 右 -> 右下
for (int i = up; i <= down; i++)
{
res[i][right] = ++num;
}
right--;
// 下边 右 -> 左
for (int i = right; i >= left; i--)
{
res[down][i] = ++num;
}
down--;
// 左边 左-> 左上
for (int i = down; i >= up; i--)
{
res[i][left] = ++num;
}
left++;
}
return res;
}
};
// left right up down 四个边界
哈希表
class Solution
{
public:
bool isAnagram(string s, string t)
{
map<char, int> hash;
for (int i = 0; i < s.size(); i++)
{
hash[s[i]]++;
};
for (int i = 0; i < t.size(); i++)
{
hash[t[i]]--;
}
for (auto iter : hash)
{
if (iter.second != 0)
{
return false;
}
}
return true;
}
};
// hash['a']++,默认值是 0
class Solution
{
public:
vector<int> intersection(vector<int> &nums1, vector<int> &nums2)
{
vector<int> res;
std::unordered_set<int> nums1_set(nums1.begin(), nums1.end());
std::unordered_set<int> nums2_set(nums2.begin(), nums2.end());
for (auto iter : nums2_set)
{
if (nums1_set.find(iter) != nums1_set.end())
{
res.emplace_back(iter);
}
}
return res;
}
};
// 集合哈希
class Solution {
public:
// 取数值各个位上的单数之和
int getSum(int n) {
int sum = 0;
while (n) {
sum += (n % 10) * (n % 10); // 不用再添加()
n /= 10;
}
return sum;
}
bool isHappy(int n) {
unordered_set<int> set;
while(1) {
int sum = getSum(n);
if (sum == 1) {
return true;
}
// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
if (set.find(sum) != set.end()) {
return false;
} else {
set.insert(sum);
}
n = sum;
}
}
};
字符串
class Solution
{
public:
void reverseString(vector<char> &s)
{
int left = 0;
int right = s.size() - 1;
while (left < right)
{
swap(s[left], s[right]);
left++;
right--;
}
}
};
class Solution
{
public:
string reverseStr(string s, int k)
{
for (int i = 0; i < s.size(); i += 2 * k)
{
if (i + k <= s.size())
{
std::reverse(s.begin() + i, s.begin() + i + k); // 反转从 i 到 i+k 的部分
}
else
{
std::reverse(s.begin() + i, s.end());
}
}
return s;
}
};
// 字符串翻转 std::reverse
class Solution
{
public:
void input_format(string &s)
{
int slow = 0;
for (int fast = 0; fast < s.size(); fast++)
{
if (s[fast] != ' ')
{
if (slow != 0)
{
s[slow++] = ' '; // 手动添加空格
}
while (fast < s.size() && s[fast] != ' ')
{
s[slow++] = s[fast++]; // 注意资源重复赋值,
};
}
}
s.resize(slow);
}
string reverseWords(string s)
{
input_format(s);
std::reverse(s.begin(), s.end());
int index = 0;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == ' ')
{
std::reverse(s.begin() + index, s.begin() + i);
index = i + 1;
}
if (i == s.size()-1)
{
std::reverse(s.begin() + index, s.end());
}
}
return s;
};
};
// 注意std::reverse 区间 [ )
class Solution
{
public:
bool repeatedSubstringPattern(string s)
{
string compare = s + s;
compare.erase(compare.begin());
compare.erase(compare.end() - 1);
if (compare.find(s) != string::npos)
{
return true;
}
return false;
}
};
二叉树
class Solution
{
private:
vector<int> res;
public:
void pre_look(TreeNode *root)
{
if (root == nullptr)
{
return;
}
res.emplace_back(root->val); // 中
pre_look(root->left);
pre_look(root->right);
}
vector<int> preorderTraversal(TreeNode *root)
{
pre_look(root);
return res;
}
};
class Solution
{
private:
vector<int> res;
public:
void sub_look(TreeNode *root)
{
if (root == nullptr)
{
return;
}
sub_look(root->left);
sub_look(root->right);
res.emplace_back(root->val); // 中
}
vector<int> postorderTraversal(TreeNode *root)
{
sub_look(root);
return res;
}
};
class Solution
{
public:
vector<int> res;
void middle_look(TreeNode *root)
{
if (root == nullptr)
{
return;
}
middle_look(root->left);
res.emplace_back(root->val); // 中
middle_look(root->right);
}
public:
vector<int> inorderTraversal(TreeNode *root)
{
middle_look(root);
return res;
}
};
class Solution
{
public:
vector<vector<int>> levelOrder(TreeNode *root)
{
vector<vector<int>> res;
vector<int> res_index;
queue<TreeNode *> queue;
if (root != nullptr)
{
queue.push(root);
}
while (!queue.empty())
{
int size = queue.size();
for (int i = 0; i < size; i++)
{
TreeNode *root_index = queue.front();
res_index.emplace_back(root_index->val);
queue.pop();
if (root_index->left)
{
queue.push(root_index->left);
}
if (root_index->right)
{
queue.push(root_index->right);
}
}
res.emplace_back(res_index);
res_index.clear();
}
return res;
}
};
回溯
class Solution
{
public:
vector<int> res_index;
vector<vector<int>> res;
public:
void back_track(int n, int k, int index)
{
// 子集满足条件
if (res_index.size() == k)
{
res.emplace_back(res_index);
return;
}
for (int i = index; i <= n; i++)
{
// 添加当前数
res_index.emplace_back(i);
// 访问下一个数
back_track(n, k, i + 1);
// 回溯
res_index.pop_back();
}
}
public:
vector<vector<int>> combine(int n, int k)
{
back_track(n, k, 1);
return res;
}
};
class Solution
{
public:
vector<vector<int>> res;
vector<int> res_index;
public:
void back_track(int n, int k, int index)
{
// 子集满足条件
if (res_index.size() == k && n >= k)
{
int sum = 0;
for (auto iter : res_index)
{
sum += iter;
}
if (sum == n)
{
res.emplace_back(res_index);
}
return;
}
for (int i = index; i <= 9; i++)
{
// 添加当前数
res_index.emplace_back(i);
// 访问下一个数
back_track(n, k, i + 1);
// 回溯
res_index.pop_back();
}
}
public:
vector<vector<int>> combinationSum3(int k, int n)
{
back_track(n, k, 1);
return res;
}
};
动态规划
小米的一道笔试题
(1)小李负责汽车采购业务。公司需要采购一批汽车,保证车可以载X人,承货Y立方米, 小李调研了市场的n种汽年。对第i种汽车价值m_i 元, 有k _i中采购方案。默认的方案可以承载x_i人,承货y_i立方米.第i种选配方案需要金额变化为m_ij元.可以选择特殊的座椅或省支架使得载人和承货能力发生变化,载人变化值为x_ij,载货变化值为y_ij。每辆车能选择一种选配方案,或者选择默认方案。
小李可以同时采购多种汽车的多种选配方案,只希望花费展少的金额满足要求。
输入描述
第一行包括三个正整数X,Y,N,这三个数取值范围都在[1,200]中.
然后是n组数据: 其中第i组第一行包括四个整教m_i,x_i,y_i,k_i,所有数均小1e5, k可能为0.接下来k_i行每行包括3个整教m_ij,x_ij.y_ij.
样例输入
10 20 2
100 2 6 1
20 1 1
80 5 1 1
10 -1 2
样例输出
390
购买第一辆车默认方案3辆,第二辆车的第一种方案1辆。 100*3+90 = 390
#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
using namespace std;
struct car
{
int cost;
int passenger;
int capacity;
};
main()
{
int X, Y, N;
cin >> X >> Y >> N;
vector<car> items; // 存储每个方案的cost, x, y
for (int i = 0; i < N; ++i)
{
int m_i, x_i, y_i, k_i;
cin >> m_i >> x_i >> y_i >> k_i;
// 添加默认方案
items.emplace_back(m_i, x_i, y_i);
// 处理选配方案
for (int j = 0; j < k_i; ++j)
{
int m_ij, x_ij, y_ij;
cin >> m_ij >> x_ij >> y_ij;
int cost = m_i + m_ij;
int x = x_i + x_ij;
int y = y_i + y_ij;
items.emplace_back(cost, x, y);
}
}
// 初始化动态规划数组
// dp表示在X,Y 情况下,最少的花费。
vector<vector<long long>> dp(X + 1, vector<long long>(Y + 1, INT_MAX));
dp[0][0] = 0;
// 处理每一辆车
for (const auto &item : items)
{
int cost, dx, dy;
cost = item.cost;
dx = item.passenger;
dy = item.capacity;
for (int a = 0; a <= X; ++a)
{
for (int b = 0; b <= Y; ++b)
{
if (dp[a][b] == INT_MAX)
continue;
// 计算新的载人和载货量
int new_a = a + dx;
// 可能会超额,比如20满足要求,选择出来多了,21,
new_a = min(new_a, X);
int new_b = b + dy;
new_b = min(new_b, Y);
// 当前的花费少
if (dp[a][b] + cost < dp[new_a][new_b])
{
// 更新dp数组
dp[new_a][new_b] = dp[a][b] + cost;
}
}
}
}
cout << dp[X][Y] << endl;
return 0;
}