挑战程序设计竞赛第二章、贪心部分

POJ2376

给你若干个线段的开始点和结束点,你需要的是把这些线段覆盖起来,使其能完整地盖住一段区间
问题是贪心,首先做的是排除那些无用的线段(起始点相同但是长度较短),然后维护一个临时的上界,注意只有当现在线段的下一个线段不能覆盖住整个区间的时候才增加下一个。
  1 #pragma GCC optimize(3)
  2 #include <time.h>
  3 #include <algorithm>
  4 #include <bitset>
  5 #include <cctype>
  6 #include <cmath>
  7 #include <cstdio>
  8 #include <cstdlib>
  9 #include <cstring>
 10 #include <deque>
 11 #include <functional>
 12 #include <iostream>
 13 #include <map>
 14 #include <queue>
 15 #include <set>
 16 #include <sstream>
 17 #include <stack>
 18 #include <string>
 19 #include <typeinfo>
 20 #include <utility>
 21 #include <vector>
 22 using namespace std;
 23 const double EPS = 1e-9;
 24 const int INF = 2147483647;
 25 const long long LLINF = 9223372036854775807;
 26 const double PI = acos(-1.0);
 27 
 28 inline int READ() {
 29     char ch;
 30     while ((ch = getchar()) < 48 || 57 < ch)
 31         ;
 32     int ans = ch - 48;
 33     while (48 <= (ch = getchar()) && ch <= 57)
 34         ans = (ans << 3) + (ans << 1) + ch - 48;
 35     return ans;
 36 }
 37 
 38 #define REP(i, a, b) for (int i = (a); i <= (b); i++)
 39 #define PER(i, a, b) for (int i = (a); i >= (b); i--)
 40 #define MP(x, y) make_pair(x, y)
 43 #define PB(x) push_back(x)
 44 #define SET(a) memset(a, -1, sizeof(a))
 45 #define CLR(a) memset(a, 0, sizeof(a))
 46 #define MEM(a, x) memset(a, x, sizeof(a))
 47 #define ALL(x) begin(x), end(x)
 48 #define LL long long
 49 #define Lson (index * 2)
 50 #define Rson (index * 2 + 1)
 51 #define pii pair<int, int>
 52 #define pll pair<LL, LL>
 53 #define MOD ((int)1000000007)
 54 #define MAXN 1000 + 5
 55 ///**********************************START*********************************///
 56 
 57 int N, T, cnt;
 58 struct cow {
 59     int l, r;
 60     cow(int x, int y) : l(x), r(y) {}
 61     bool operator<(const cow &rhs) const {
 62         return l == rhs.l ? r > rhs.r : l < rhs.l;
 63     }
 64 };
 65 set<cow> s;
 66 map<int, int> mp;
 67 
 68 int main() {
 69     // freopen("input.txt", "r", stdin);
 70     N = READ(), T = READ();
 71     pii a;
 72     REP(i, 1, N) {
 73         a.first = READ(), a.second = READ();
 74         if (mp[a.first] < a.second) mp[a.first] = a.second;
 75     }
 76     /*  cout << endl;
 77      for (auto i : mp) cout << i.first << " " << i.second << endl; */
 78     int up = 0, tmp = 0, flag = 0;
 79     for (map<int, int>::iterator i = mp.begin(); i != mp.end(); i++) {
 80         int l = (*i).first, r = (*i).second;
 81         if (l <= up + 1) {
 82             if (r > tmp) {
 83                 tmp = r;
 84                 flag = 1;
 85             }
 86             map<int, int>::iterator it = i;
 87             it++;
 88             if ((it == mp.end() && up < T && tmp >= T) ||
 89                 ((*it).first > up + 1 && flag)) {
 90                 up = tmp;
 91                 cnt++;
 92                 flag = 0;
 93             }
 94         }
 95     }
 96     if (up >= T)
 97         printf("%d", cnt);
 98     else
 99         printf("-1");
100     return 0;
101 }

 

  

POJ2393

题意:每周可以生产牛奶,每周生产的价格为Ci,每周需要上交的牛奶量Yi,你可以选择本周生产牛奶,也可选择提前几周生产出存储在仓库中(仓库无限大,而且保质期不考虑),每一周存仓库牛奶需要花费S元,让你求出所有周的需求量上交的最少花费。

解:核心是找到当前这一周前面最近的且价格最低的那一周,直接找会N2超时,转换思路,从前到后遍历,将每一周的价格修改为从前一周保存还是从当前周购买(将最优的策略传递下来),这样子你面临的就是已有的当前可以选择的最优解和现在的最优解。

 

 1 int N, S;
 2 int c[MAXN], y[MAXN];
 3 LL ans;
 4 
 5 int main() {
 6     // READ_FROM_FILE;
 7     N = READ(), S = READ();
 8     REP(i, 1, N) c[i] = READ(), y[i] = READ();
 9     REP(i, 2, N) c[i] = min(c[i - 1] + S, c[i]);
10     REP(i, 1, N) ans += c[i] * y[i];
11     printf("%lld", ans);
12     return 0;
13 }

 

 POJ3040

题意:有N种硬币,每个有B个,你每天需要给某人价值为C的硬币,问怎样安排可以让给的时间最长

解法:贪心策略,先拿大的,然后用小的补齐,这个实现的时候挺有技巧的,注意代码

 1 struct COIN {
 2     int val, num;
 3     bool operator<(const COIN& rhs) const { return val > rhs.val; }
 4 } a[MAXN];
 5 int N, c;
 6 int main() {
 7     // freopen("input.txt", "r", stdin);
 8     scanf("%d%d", &N, &c);
 9     for (int i = 1; i <= N; i++) scanf("%d%d", &a[i].val, &a[i].num);
10     sort(a + 1, a + 1 + N);
11     int ans = 0, pos;
12     for (int i = 1; i <= N; i++) {
13         if (a[i].val >= c) {
14             ans += a[i].val / c * a[i].num;
15         } else {
16             pos = i;
17             break;
18         }
19     }
20     while (1) {
21         int now = 0;
22         for (int i = pos; i <= N; i++) {
23             while (a[i].num && a[i].val + now <= c) {
24                 now += a[i].val;
25                 a[i].num--;
26             }
27         }
28         for (int i = N; i >= pos; i--) {
29             while (a[i].num && now < c) {
30                 now += a[i].val;
31                 a[i].num--;
32             }
33         }
34         if (now < c) break;
35         ans++;
36     }
37     printf("%d\n", ans);
38     return 0;
39 }

 

 

转载于:https://www.cnblogs.com/romaLzhih/p/11406021.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值