洛谷P2577 午餐

题目链接

题意概述:有n个人,第i个人打饭消耗ai时间,离开后吃饭耗费bi时间,将n个人分成两队,合理分配人员使总时间最短并输出总时间。

  我们把问题拆分为两个部分。首先是排列顺序,然后是怎么分到两个队伍中。

  显然吃饭越慢应该越早打饭,因为打饭总时间不变那么让吃的慢的人早开始吃会使总时间最小。

  那么现在我们只需要分一下人就好了。看一眼数据发现n<=200,可以使用随机分配。

  时间复杂度:O(跑的出来)

  

#include<cstring>
#include<iostream>
#include<cctype>
#include<cstdio>
#include<algorithm>
#include<ctime>
using namespace std;
inline int read()
{
    register int X=0;register char ch=0;bool flag=0;
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') flag=1;
    for(;isdigit(ch);ch=getchar()) X=(X<<3)+(X<<1)+ch-'0';
    return (flag ? -X : X);
}
inline void write(int x)
{
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
int n;
struct person
{
    int eat,get;
}p[201];
int ans=2147483647;
int f[1001];
bool cmp(person xx,person yy){return xx.eat>yy.eat;}
int max(int a,int b){return a>b ? a : b;}
int min(int a,int b){return a>b ? b : a;}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        p[i].get=read(),p[i].eat=read();
    sort(p+1,p+n+1,cmp);
    for(int i=1;i<=1000;i++)
        f[i]=(i&1 ? 1 : 0);
    while(clock()<900000)
    {
        random_shuffle(f+1,f+1001); 
        int sum1=0,sum2=0,tot1=-1,tot2=-1;
        for(int j=1;j<=n;j++)
        {
            if(f[j] & 1)
                sum1+=p[j].get,tot1=max(tot1,sum1+p[j].eat);
            else
                sum2+=p[j].get,tot2=max(tot2,sum2+p[j].eat);
            if(tot1 > ans || tot2 > ans) break;
        }
        ans=min(ans,max(tot1,tot2));
    }
    printf("%d\n",ans);
}

 

  

posted @ 2018-09-01 11:11  _hcy_a  阅读(185)  评论(0编辑  收藏  举报