zoukankan      html  css  js  c++  java
  • UPC-6198 JL的智力大冲浪(简单贪心)

    题目描述
    JL报名参加LCYZ的智力大冲浪节目。本次挑战赛吸引了众多参赛者,主持人为了表彰大家的勇气,先奖励每个参赛者m元。先不要太高兴!因为这些钱还不一定都是你的?!接下来主持人宣布了比赛规则:
    首先,比赛时间分为n个时段(n≤500),它又给出了很多小游戏,每个小游戏都必须在规定期限ti前完成(1≤ti≤n)。如果一个游戏没能在规定期限前完成,则要从奖励费m元中扣去一部分钱wi,wi为自然数,不同的游戏扣去的钱是不一样的。当然,每个游戏本身都很简单,保证每个参赛者都能在一个时段内完成,而且都必须从整时段开始。主持人只是想考考每个参赛者如何安排组织自己做游戏的顺序。作为参赛者,JL很想赢得冠军,当然更想赢取最多的钱!注意:比赛绝对不会让参赛者赔钱!
    输入
    共4行。
    第1行为m,表示一开始奖励给每位参赛者的钱;
    第2行为n,表示有n个小游戏;
    第3行有n个数,分别表示游戏1到n的规定完成期限;
    第4行有n个数,分别表示游戏1到n不能在规定期限前完成的扣款数。
    输出
    仅1行。表示JL能赢取最多的钱。
    样例输入
    10000
    7
    4 2 4 3 1 4 6
    70 60 50 40 30 20 10
    样例输出
    9950

    一道贪心水题,一开始被自己的代码卡了好久,基本思路就是贪心,后来在网上看别人的博客时发现他们竟然对价值排序,很不理解,总之我是按时间排序,先做能做的。时间一样按价值排序,先做扣钱多的。然后重点来了,一个简单的500范围,直接n方暴力就好,我们对一个新遍历到的游戏,发现如果无法完成,那么我们就遍历之前完成过的所有游戏,找一个花费最少的,然后与新游戏比较,取花费最小的舍去,给了选择一个反悔的机会。这样每次取最优解,一旦发现有任务完成不了,就找一个做过的游戏来比较,替换。这样保证我们每次舍去的都是一个最小花费。并且舍去的游戏不再作为参考项,因为按时间排序,所有待选项必须都在当时的时间下可以被完成,要么我用之前完成过其他游戏的时间完成后来的任务,要么我不要后来的任务,就按顺序做好之前能做的任务,这是按时间排序过的,舍去的,就已经过了时间,失去了反悔的机会。

    需要注意的是,我们遍历的是已经做过的游戏,那么对于没有做过的游戏我们不做遍历,因此要对做过的游戏做一个标记,并且在后来的取舍中。被取到的游戏要标记,被舍去的游戏要取消标记。以便后来的遍历中,仍然可以拿此次的选择作为舍去的待选项。

    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    #define LL long long
    using namespace std;
    struct  node
    {
        int t,w;
    } a[506];
    bool vis[506];
    bool cmp(node a,node b)
    {
        if(a.t==b.t)return a.w>b.w;
        return a.t<b.t;
    }
    int main()
    {
        int m,n;
        while(scanf("%d",&m)!=EOF)
        {
            memset(vis,false,sizeof(vis));
            scanf("%d",&n);
            for(int i=1; i<=n; i++) scanf("%d",&a[i].t);
            for(int i=1; i<=n; i++) scanf("%d",&a[i].w);
            sort(a+1,a+n+1,cmp);
            int i=1,time=1;
            while(i<=n)
            {
                if(a[i].t>=time)
                {
                    vis[i]=true;
                    time++;
                }
                else
                {
                    int minn=0x7fffffff,mini=i;
                    for(int k=1; k<i; k++)
                        if(a[k].w<minn&&vis[k])
                        {
                            minn=a[k].w;
                            mini=k;
                        }
    //                printf("-------%d
    ",minn);
                    if(minn<a[i].w)
                    {
                        m-=minn;
                        vis[i]=true;
                        vis[mini]=false;
                    }
                    else m-=a[i].w;
                }
                i++;
    //            printf("%d=====%d
    ",a[i].t,m);
            }
            printf("%d
    ",m<0?0:m);
        }
    }
    /*
    1000
    9
    1 1 1 3 4 5 2 2 2
    30 60 90 100 100 100 30 60 90
    
    3000
    8
    1 2 2 3 4 4 4 4
    10 10 10 10 100 100 100 100
    */
    
  • 相关阅读:
    从滴滴flinkCEP说起
    从零讲Java,给你一条清晰地学习道路!该学什么就学什么!
    从coalesce算子发散开的
    从架构理解价值-我的软件世界观
    为什么说Redis是单线程的?
    全排列_获取第几个排列_获取是第几个排列__康托展开,逆康托展开
    求排列是全排列的第几个,求第几个是全排列___康托展开,逆康托展开
    搜索入门_简单搜索bfs dfs大杂烩
    无根树同构_hash
    乘法逆元_三种方法
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135809.html
Copyright © 2011-2022 走看看