题解 P3093 【[USACO13DEC]牛奶调度Milk Scheduling】

· · 题解

单纯的贪心,考虑到选择的问题,担心的就是前面的选择会不会对后面选择造成影响,所以我们换个方向考虑一下,也就是利用贪心思想了

我们按照加仑牛奶的价值进行一个排序,优先挤价值大的肯定是没错的,然后就是考虑,用哪一时间去挤得问题,这个其实也很好解决,因为每个时间点只能挤一头奶牛的奶,所以我们按照每个奶牛最后的选取时间往前找,尽量找到靠后面的时间不就可以了嘛

有没有觉得问题一下子豁然开朗了?

那么接下来的问题很简单定义结构体,按照牛奶价值给结构体排序。可能有点人还不是太会,我这里提供一个自己写的昂(dalao别笑):

int cmp(love x,love y)
{
    return x.milk>y.milk;
}

剩下的就更简单了,循环到每一个奶牛,然后看看能否挤奶,能就加和,不能就跳过。

问题就这么解决了,下面上代码(只提供借鉴,不准复制粘贴):

#include<bits/stdc++.h>//偷懒专用库 
#define ll long long
#define INF 15200
#define MAXN 99999//宏定义 
using namespace std;

inline int read(){
  char c=getchar();int x=0,f=1;
  while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
  while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
  return x*f;
}//这里是快读,可以提供借鉴,忽略掉也无所谓的 

struct love
{
    int milk;
    int time;
}you[INF];//定义一个机构体 

int cmp(love x,love y)
{
    return x.milk>y.milk;
}//结构体排序,按照加仑牛奶的价值从大到小排,先处理价值大的,保证不能挤得越小越好 

int n,ans,tot;
int a[INF];//判断这个时间点挤没有挤过奶 

int main()//主函数部分 
{
    n=read();//读入 
    for(int i=1;i<=n;++i)
      {
        you[i].milk=read();
        you[i].time=read();
      } //读入加仑牛奶价值和挤得最后时间 
    sort(you+1,you+1+n,cmp);//排序 
    for(int i=1;i<=n;++i)//判断是否能挤 
     {
        tot=0;//这是一个判断用的东西,待会就明白了 
        for(int j=you[i].time;j>=1;--j)//从他的最大时间开始,一直到一,看看有没有一个时间点没挤过 
         {
            if(a[j]==0)//如果这个点没挤过,就代表当前的牛奶可以被挤 
             {
                a[j]=1;//把这个点变成挤过 
                tot=1;//然后标记成挤过 
                break;//跳出循环 
             }//因为此时找到是最晚能挤的时间,所以不会影响以后的选择 
         }
        if(tot==1)
         ans+=you[i].milk;//如果标记过,证明奶挤过,所以答案加上价值 
     }
    cout<<ans;//输出
    return 0;//养成好习惯,从你我做起 
}

给蒟蒻一个赞吧,蒟蒻还没有赞呢