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\n",minn);
                if(minn<a[i].w)
                {
                    m-=minn;
                    vis[i]=true;
                    vis[mini]=false;
                }
                else m-=a[i].w;
            }
            i++;
//            printf("%d=====%d\n",a[i].t,m);
        }
        printf("%d\n",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
*/
posted @ 2018-03-28 01:43  KuroNekonano  阅读(128)  评论(0编辑  收藏  举报