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


Problem Description
Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher gives him a deadline of handing in the homework. If Ignatius hands in the homework after the deadline, the teacher will reduce his score of the final test. And now we assume that doing everyone homework always takes one day. So Ignatius wants you to help him to arrange the order of doing homework to minimize the reduced score.
 

Input
The input contains several test cases. The first line of the input is a single integer T that is the number of test cases. T test cases follow.
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.
 

Output
For each test case, you should output the smallest total reduced score, one line per test case.
 

Sample Input
333 3 310 5 131 3 16 2 371 4 6 4 2 4 33 2 1 7 6 5 4
 

Sample Output
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。

0 0
原创粉丝点击