算法入门训练之南——1.11勇者斗恶龙
你的王国里有一条n头的巨龙,你希望雇一些骑士把它杀死(即砍掉所有头)。
一个能力值为x的骑士可以砍掉恶龙一个直径不超过x的头,且需要支付x个金币。
如何雇佣骑士才能砍掉恶龙所有的头,且需要支付的金币最少?
注意,一个骑士只能砍一个头(且不能被雇用两次)。
【输入格式】
输入包含多组数据。每组数据第一行为正整数n和m(1《=n,m<=20000);
以下n行每行为一个整数,即每个恶龙头的直径;
以下m行每行为一个整数,即每个骑士的能力。
输入结束的标志为n=m=0。
【输出格式】
对于每组数据,输出最少花费。
如果无解,输出“Loowater is doomed!”。
【样例输入】
- 2 3
- 5
- 4
- 7
- 8
- 4
- 2 1
- 5
- 5
- 10
- 0 0
【样例输出】
- 11
- Loowater is doomed!
【分析】能力强的骑士开价高是合理的,但如果被你派去砍一个很弱的头,就是浪费人才了。
因此,可以把雇佣来的骑士按照能力从小到大排序,所有的头按直径从小到大排序,一个个砍就可以了。
当然不能砍掉“当前需要砍的头”的骑士就不要雇佣了。
代码如下。
#include<cstdio>
#include<algorithm> //because of the use of sort
using namespace std;
const int maxn = 2005;
int A[maxn], B[maxn];
int main() {
int n, m;
while(scanf("% %d",&n,&m) == 2 &&n &&m){ // get a new skill
for(int i=0;i<n;i++) scanf("%d",&A[i]);
for(int i=0;i<m;i++) scanf("%d",&B[i]);
sort(A,A+n);
sort(B,B+m);
int cur = 0;
int cost = 0;
for(int i=0; i<m;i++)
if(B[i]>=A[cur]){
cost+=B[i];
if(++cur == n) break;
}
if(cur <n) printf("Loowater is doomed!\n");
else printf("%d\n",cost);
}
return 0;
}
- //以上是书上给出的解题思路,是比较好的方法。当然这题的方法肯定不止一种,或优或劣。
- 分析:
- 思路二:不排序,直接对每个巨龙头的直径检索骑士能力值。取大于等于直径的能力值的骑士。
- 对上述思路的质疑。是否会造成能力值浪费,留给读者们思考。