洛谷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); }
忘开longlong,忘用逆元,忘删调试信息,瞬间爆炸