题意:
给出四种轮班制度
要求:
工作日白天每天有n1个人
休息日白天每天有n2个人
晚上每天有n3个人(不分工作日还休息日)
问:怎么样安排这四种不同轮班制度的人数可以使得总人数最少
题解:
schedule 1:机动性很高,但是三天才轮班一次
schedule 2:机动性最低,但是工作日每天都要工作
schedule 3:机动性高并且工作量也大
schedule 4:机动性中等,因为白天只能在工作日工作,但是晚上可以在任意时间工作
为保证每天都有相应的人手在工作,所以每一种 schedule 都需要一定量的人来循环工作
schedule 1 至少需要三个人同时工作才可以覆盖一周
schedule 2 显然只需要一个人就行了
schedule 3 需要四个,而不是三个,因为每个人工作周期的尾部有一个休息天
schedule 4 同理需要五个
题目要求需要人数最少:
那么先选择机动性最高并且工作量大的,这样避免人数过多且不能覆盖周末
故选择顺序为 3 4 1 2
注意1比二先是因为1需要先覆盖周末的白天
最后需要注意理解的就是:每一种 schedule 可以看做每天都有人工作,因为我们用循环代替了
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define INF 1000000000
int main()
{
int n1,n2,n3;
int a1,a2,a3,a4;
//freopen("in.txt","r",stdin);
freopen("guards.in","r",stdin);
freopen("guards.out","w",stdout);
while(scanf("%d%d%d",&n1,&n2,&n3)!=EOF)
{
int p1,p2,p3;
int k1,k2,k3;
int sum,MIN=INF;
int t1,t2,t3,t4;///四种上班方式
for(t3=0;;t3++){///枚举第三种上班方式
p1=n1-2*t3,p2=n2-2*t3,p3=n3-t3;
for(t4=0;;t4++){
k1=p1-3*t4,k2=p2,k3=p3-2*t4;
t1=max(0,max(k2,k3));///占据上夜班或者周末白班
t2=max(0,k1-t1);///因为循环问题,安排去周末白班的最后也会到工作日白班
sum=t1*3+t2+t3*4+t4*5;
if(sum<=MIN)
MIN=sum,a1=t1*3,a2=t2,a3=t3*4,a4=t4*5;
if(k1<=0&&k3<=0)///注意k2没变化,所以不能再这里判断
break;
}
if(p1<=0&&p2<=0&&p3<=0)
break;
}
printf("%d %d %d %d\n",a1,a2,a3,a4);
}
return 0;
}