- 简单贪心
- [FatMouse' Trade](http://acm.hdu.edu.cn/showproblem.php?pid=1009)
- [Senior's Gun](http://acm.hdu.edu.cn/showproblem.php?pid=5281)
- 区间贪心
- 今年暑假不AC
- **[POJ 1328 Radar Installation](http://poj.org/problem?id=1328)**
简单贪心 FatMouse’ Trade
- 贪心策略
- 问题分解为多个子问题
- 子问题求局部最优解
- 局部最优解组合成原问题的解
尽可能多的咖啡豆:贪心策略
注意:商品可以任意切分,无需买完
- 贪心策略
- 每次购买一件商品
- 选“性价比”最高的商品
- 已经购买商品的累和
#includeSenior’s Gun#include #include #include #include using namespace std; const int MAXN = 1000; struct JavaBean { double weight;//JavaBeans double cost;//cat food }; JavaBean arr[MAXN]; bool Compare(JavaBean x, JavaBean y) { return x.weight / x.cost > y.weight / y.cost; } int main() { int n, m; while (scanf("%d%d", &m, &n) != EOF) { if (n == -1 && m == -1) { break; } for (int i = 0; i < n; i++) { scanf("%lf%lf", &arr[i].weight, &arr[i].cost); } //每个房间兑换性价比从高到底 sort(arr, arr + n, Compare); double answer = 0; for (int i = 0; i < n; i++) { //如果够买完这个房间 if (m >= arr[i].cost) { m -= arr[i].cost; answer += arr[i].weight; } //如果不够兑换完整个房间,按百分比兑换 else { answer += arr[i].weight * (m / arr[i].cost); m = 0; break; } } printf("%.3fn", answer); } return 0; }
#include区间贪心 今年暑假不AC#include #include #include #include using namespace std; const int MAXN = 100000 + 10; long long gun[MAXN]; long long monster[MAXN]; bool Compare(long long x, long long y) { return x > y; } int main() { int caseNumber; scanf("%d", &caseNumber); while (caseNumber--) { int n, m; scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) { scanf("%lld", &gun[i]); } for (int j = 0; j < m; j++) { scanf("%lld", &monster[j]); } //枪伤害力从大到小 sort(gun, gun + n, Compare); //怪物防御力从小到大 sort(monster, monster + m); long long answer = 0; for (int i = 0; i < n; i++) { //如果枪的数量大于怪兽的数量,或者枪无法打死最弱怪物 //没有任何收益跳出 if (i >= m || gun[i] <= monster[i]) { break; } answer += gun[i] - monster[i] ; } printf("%lldn", answer); } return 0; }
- 选择开始时间最早的
- 选择持续时间最短的
- 选择结束时间最早的
- 贪心策略
- 每次只选一个节目
- 选择结束最早的节目
- 所有节目的数目
#includePOJ 1328 Radar Installation#include #include #include #include using namespace std; const int MAXN = 100 + 10; struct program { int startTime; int endTime; }; program arr[MAXN]; bool Compare(program x, program y) { return x.endTime < y.endTime; } int main() { int n; while (scanf("%d", &n) != EOF) { if (n == 0) { break; } for (int i = 0; i < n; i++) { scanf("%d%d", &arr[i].startTime, &arr[i].endTime); } //节目结束时间从早到晚排列 sort(arr, arr + n, Compare); //当前时间 int current = 0; int answer = 0; for (int i = 0; i < n; i++) { //当前时间小于节目的开始时间可以观看 if (current <= arr[i].startTime) { current = arr[i].endTime; answer++; } } printf("%dn", answer); } return 0; }
以小岛为圆心d为半径画圆
贪心策略
- 每次只选一个区间
- 选择左端点最小的区间
- 重叠区间的数目
#include#include #include #include #include using namespace std; const int MAXN = 1000 + 10; struct Interval { double left; double right; }; Interval arr[MAXN]; bool Compare(Interval a, Interval b) { return a.left < b.left; } int main() { int n, d; int caseNumber = 1; while (scanf("%d%d", &n, &d) != EOF) { if (n == 0 && d == 0) { break; } //标志雷达是否能覆盖所有岛屿 bool flag = true; for (int i = 0; i < n; i++) { int x, y; scanf("%d%d", &x, &y); //相离,永远不可能覆盖到 if (y > d) { flag = false; } else {//相交和相切 arr[i].left = x - sqrt(d * d - 1.0 * y * y); arr[i].right = x + sqrt(d * d - 1.0 * y * y); } } //输出 if (!flag) { printf("Case %d: %dn", caseNumber++, -1); } else { sort(arr, arr + n, Compare); //假设初始化当前第一个雷达站点 double current = arr[0].right; int answer = 1;//雷达数目 for (int i = 1; i < n; i++) { //区间重叠 ,照顾两头取最佳 if (arr[i].left <= current) { current = min(current, arr[i].right); } else { //区间不重叠,新建雷达站 current = arr[i].right; answer++; } } printf("Case %d: %dn", caseNumber++, answer); } } return 0; }



