hdu 4546 比赛难度 (PFS,优先级优先搜索)

Problem - 4546

  题目是中文的,不解释了。

  开始的时候不知道怎么可以搞出答案,就觉得这个是需要搜索的。于是就想到逐个数加上去,然后只取前m小的和,其余的弹出集合这种方法。为了可以动态维护这前m个最小的和,我用了multiset,又为了不会搜索到超出内存什么的,所以我在搜索的时候采取了剪枝,如果求和得到的数比现在集合中最大的数还要大,当前和跟之后的所有数的和都会大于集合中的最大数,这时就不用继续搜索下去了。(原始单个数的结合已进行排序)

代码如下:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cctype>
 5 #include <set>
 6 
 7 using namespace std;
 8 
 9 typedef long long LL;
10 typedef pair<int, int> PII;
11 #define MPR make_pair
12 
13 const int N = 11111;
14 multiset<PII> has;
15 int rec[N];
16 
17 int main() {
18     int T, n, m;
19     multiset<PII>::iterator cur, tmp;
20     scanf("%d", &T);
21     for (int cas = 1; cas <= T; cas++) {
22         scanf("%d%d", &n, &m);
23         has.clear();
24         for (int i = 0; i < n; i++) {
25             scanf("%d", &rec[i]);
26         }
27         sort(rec, rec + n); // 单个元素由小到大排序
28         for (int i = 0; i < n; i++) {
29             has.insert(MPR(rec[i], i)); // 把单个元素的情况先塞进集合,PII中第一个是当前的和,第二个是当前和已经枚举到第几个元素了
30             if (has.size() > m) { // 如果超出容量,就删除最大的和
31                 tmp = has.end();
32                 tmp--;
33                 has.erase(tmp);
34             }
35         }
36         cur = has.begin();
37         while (cur != has.end()) {
38             int fi = (*cur).first, se = (*cur).second; // 将和为cur.first的元素拓展,当前和最后加入的元素的下标是cur.second
39             for (int i = se + 1; i < n; i++) {
40                 if (has.size() < m) {
41                     has.insert(MPR(fi + rec[i], i));
42                 } else {
43                     tmp = has.end();
44                     tmp--;
45                     if (fi + rec[i] >= (*tmp).first) break;
46                     has.insert(MPR(fi + rec[i], i));
47                     has.erase(tmp);
48                 }
49             }
50             cur++;
51         }
52         tmp = has.end();
53         tmp--;
54         printf("Case #%d: %d\n", cas, (*tmp).first);
55     }
56     return 0;
57 }
View Code

 

——written by Lyon

转载于:https://www.cnblogs.com/LyonLys/archive/2013/05/21/hdu_4546_Lyon.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值