旅行传送门:快来点我鸭
题目背景
你作为一个村的村长,保卫村庄是理所当然的了.今天,村庄里来了一只恶龙,他有n个头,恶龙到处杀人放火。你着急了。不过天无绝人之路,现在来了一个骑士团。里面有m位成员(往下看)
题目描述
每个人都可以砍掉一个大小不超过(<=)z的头,要money个金币,求最小花费。
输入格式
第一行两个整数 n m
下接n行,一个整数 表示n个头的大小。
下接m行,每个人可以砍的头大小或金币(金币==头的大小)。
输出格式
一个整数,最小花费。如果无解,输出“you died!”
输入输出样例
输入 #1复制
2 3
5
4
7
8
4
输出 #1复制
11
说明/提示
1<=n,m<=20000
解题思路
很久很久以前,巨龙突然出现~
用两个优先队列分别维护头的大小和每个人可以砍的头的大小,即保证花最少的钱砍最小的头。如果当前成员不能砍掉队列最前端的头(即最小的头),那说明他也不可能砍掉之后的头,(既然如此就没有存在的必要了,毁灭吧赶紧的 );而如果可以砍掉,每个人也只能砍一个头,所以不管能不能砍掉,都需要pop当前成员换下一位。当成员队列为空而头队列不为空时,说明无解,否则输出最小花费。
AC代码
#include <bits/stdc++.h>
#define MAXN 20000 + 10
using namespace std;
int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
int main(int argc, char const *argv[])
{
int n = read(), m = read(), money = 0, temp;
priority_queue<int, vector<int>, greater<int>> heads;
priority_queue<int, vector<int>, greater<int>> humen;
for (int i = 0; i < n; i++)
{
temp = read();
heads.push(temp);
}
for (int i = 0; i < m; i++)
{
temp = read();
humen.push(temp);
}
while (!humen.empty())
{
if (heads.empty())
break;
if (humen.top() >= heads.top())
{
//如果当前成员能砍掉最前端的头,则加上当前成员的花费。
money += humen.top();
heads.pop();
}
humen.pop();
}
if (!heads.empty())
puts("you died!");
else
printf("%d\n", money);
return 0;
}