ACM_贪心(HDU2037&HDU1789)

1.贪心算法是ACM十分常用的手法,这是一种求最优解的策略。通过将求解一个整体最优解的问题分割求解一些局部最优解的问题。这种思想被用在接下来很多的算法中,比如最小生成树的普里姆算法其中就有贪心的思想。我们通过实际的例子来感受这种算法。

2.今年暑假不AC。拿到这个题目我们按照很常规的思想来思考:我们肯定是想要选取那些结束的早,持续的时间短的节目来观看,这样才能达到观看的节目最多。那么我们的思想其实就是一个贪心的思想,这里的贪心的体现就是:我们需要选区时间持续的短,并且结束的早的节目来观看。那么我们的算法可以这样实现:首先使用结构体来保存两个时间点,按照结束的时间进行排序,那么数组内的每一个结构体就是按照结束的时间进行排列,那么我们只需要比较每一个结构体开始的时间和下一个结构体开始的时间即可。具体的代码的实现如下:

#include<iostream>
#include<algorithm>
using namespace std;
struct time
{
    int st;
    int end;
}t[105];
bool cmp(time&t1, time&t2) { return t1.end < t2.end; }
int main()
{
    int n;
    while (cin >> n&&n)
    {
        for (int i = 0; i < n; i++)
        {
            cin >> t[i].st >> t[i].end;
            
        }
        sort(t, t + n,cmp);
        int num = 1;
        int tem = t[0].end;
        for (int i = 1; i < n; i++)
        {
            if (t[i].st >= tem)
            {
                num++;
                tem = t[i].end;
            }
        }
        cout << num << endl;
    }

    return 0;
}

3.写作业。看到这个题目,我们还是按照常规的思想:我们肯定是要去做哪些扣分多,时间紧急的题目。而且这个题目还有一些先决的条件,就是每一项作业都是一天完成的,也就是说所有的作业的权重是一样的,这样我们就不用考虑权重的问题。其实我们在上边的分析中就已经使用了贪心的思想:我们需要做哪些扣分多并且时间紧的作业,所以我们重排所有作业的标准又出来了,这个标准就是我们首先按照分数的多少进行排列,分数相同就按照时间排列。排列完成以后我们遍历整个数组,对于每一项作业我们来查找它的合适的位置,这样我们有需要一个数组来标记这一天是否被安排。通过以上的分析,我们给出实现的源代码:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
struct time
{
    int d;
    int s;
}t[1005];
bool Cmp(time&t1, time&t2)
{
    if (t1.s != t2.s)return t1.s > t2.s;
    else return t1.d < t2.d;
}
int use[1005];
int main()
{

    int T;
    int num;
    while (cin >> T)
    {
        for (int i = 0; i < T; i++)
        {
            cin >> num;
            for (int i = 0; i < num; i++)
            {

                cin >> t[i].d;
            }
            for (int i = 0; i < num; i++)
            {

                cin >> t[i].s;
            }
            sort(t, t + num, Cmp);
            int score = 0;
            memset(use, 0, sizeof(use));
            for (int i = 0; i < num; i++)
            {
                int flag = 0;
                for (int j = t[i].d - 1; j >= 0; j--)
                {
                    if (!use[j])
                    {
                        use[j] = 1;
                        flag = 1;
                        break;
                    }
                }
                if (!flag)score += t[i].s;
            }
            cout << score << endl;
        }
    }
    return 0;
}

以上就是贪心的两个典型的例子,贪心想要做的就是把求解一个整体最优转化为局部最优之和,但是我们都知道的是,整体最优不一定是局部最优之和。一个很简单的例子,对于一个F(x)=G(x)+T(x),求F的最大值,我们不能直接把G和T的最大值求出来加起来。这个时候就是整体最优不再简单的等于局部最优之和。所以贪心的使用是有一定的条件的。使用贪心的思想来设计程序的时候需要注意这些问题。

猜你喜欢

转载自blog.csdn.net/weixin_41863129/article/details/83097974