ACM-贪心策略
来源:互联网 发布:软件风格 编辑:程序博客网 时间:2024/05/17 03:02
在大多数的比赛中,可以使用贪心思想解决的题目,都是属于简单题一类的,之所以简单并不是说想都不用想就可以求出答案来的,相反,有些题目甚至想破头皮也想不出来,但是一看解题报告,却发现写法相当简单,难的是正确的贪心策略想不到。所以,我们说,贪心题的关键时找一个正确、有效的策略,使得结果最优。如何去找呢?先不忙,首先应该确定的是有没有这样的策略?了解过贪心算法的人,应该知道并不是所有的问题都可以使用它来解决的,原因就是贪心仅仅关注了局部的最优解。所以,当我们判断一个问题能不能使用贪心策略解决时,可以参考如下规则:
1、整体可以化为局部。
2、局部存在最优解。
3、局部与局部之间满足无后效性(即当前所做策略不会影响以前的状态)。
4、局部最优解可以推出整体最优解。
如果确定一个问题可以使用贪心求解,那么该如何求解呢?其实这个过程并没有固定的算法,问题的关键是贪心策略的选择。所以,下面仅仅给出一般过程:
1、选取问题的某个状态作为初始状态,并以此作为出发点。
2、循环求解,在这个过程中,根据我们采取的贪心策略,求出局部最优解。
3、利用局部最优解求出整体最优解。
利用上面的知识,下面我们就实际操作一次,HDOJ:1789,时空转移(点击打开链接),题目如下:
Doing Homework again
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6734 Accepted Submission(s): 4023
Each test case start with a positive integer N(1<=N<=1000) which indicate the number of homework.. Then 2 lines follow. The first line contains N integers that indicate the deadlines of the subjects, and the next line contains N integers that indicate the reduced scores.
333 3 310 5 131 3 16 2 371 4 6 4 2 4 33 2 1 7 6 5 4
035
题意:
有n门课,每一门课有一个限定的时间和超过时间后罚的分数,然后假定每一天只能完成一门课,问如何安排时间去完成这些课,使得罚分最少并输出。
分析:
读完题目就知道,就是要求找出一种安排策略,让罚分最少。很明显,这里的策略是具有贪心性质的,那接下来的关键就是如何找出正确的策略了。首先,我们应该确定的是该从哪一个状态出发?但是,无论是哪一个状态,都涉及到分数和时间两个元素,这种情况下就无法清晰的判定哪一门课应该先做,如可能有一门课的期限短但罚分少,而另一门课的期限较长但罚分较多。所以,如果有一种策略能控制一个影响因素不变就好了。事实上,这样的策略是存在的,那就是由罚分去枚举天数,由于我们的最终目的就是要让总罚分最少,那我们就贪心的先考虑罚分较多的,然后每当考虑一门课,扫描期限内的天数(注意要从最后的期限往前枚举,给其它课尽可能的留下余地),如果能完成,就将该天标记,否则计入总罚分,以此类推。
源代码:
#include <cstdio>#include <algorithm>#include <cstring>using namespace std;struct Node{ int dl; int scr;} data[1005];int vis[1005];int cmp (Node a, Node b){ if (a.scr != b.scr) return a.scr > b.scr; else return a.dl < b.dl;}int main (){//freopen("sample.txt", "r", stdin); int cas; scanf ("%d", &cas); while (cas--) { int n; memset (vis, 0, sizeof(vis)); scanf ("%d", &n); for (int i=0; i<n; ++i) scanf ("%d", &data[i].dl); for (int i=0; i<n; ++i) scanf ("%d", &data[i].scr); sort (data, data+n, cmp); int ans = 0; for (int i=0; i<n; ++i) { int j=data[i].dl; for (; j>=1; --j) // 枚举每一个合法的天数 if(!vis[j]) { vis[j] = 1; break; } if(j == 0) ans += data[i].scr; } printf ("%d\n", ans); } return 0;}
遗憾的是,对于每一道贪心的题目,基本上没有太过相似的策略,这样的话就需要我们平时多练、多思考,做题的时候才能比较快速、准确的找出方法去应付题目中比较隐晦难懂条件,其它类似的题目还有,HDOJ:1009、1257、4803。
- ACM-贪心策略
- 贪心策略
- 贪心法,贪心策略
- poj1456--贪心策略
- 算法导论-贪心策略
- hdu4562(贪心策略+DP)
- UVALive 7483 贪心策略
- ZOJ1012-Mainframe 贪心策略
- 【贪心策略】渡河(river)
- 贪心+思维策略
- 贪心策略笔记
- ACM--贪心算法
- ACM 贪心算法
- HDU ACM 1050 贪心
- ACM贪心 HDOJ1050
- 1004贪心算法acm
- 1006-贪心算法acm
- acm 贪心总结
- cocos2dx面试题-第二波
- 共轭梯度法(Conjugate Gradient Methods-CG)在回归分析的应用和比较
- [Leetcode] Permutations
- Struts是怎么运行的?
- “短线神刀”李旭东投资简历
- ACM-贪心策略
- cocoapods的安装与使用
- Jquery中dialog使用小记
- C++各种进制数据输入
- 外键约束详解
- 我的ps失误经验贴
- rhsa型asp木马隐藏分析
- Codeforces 475C Kamal-ol-molk's Painting 模拟
- 《Linux程序设计》——开发工具