题面
扫码支付如今已普及应用在大型超市,街边小贩等多个消费支付的场景,刷脸支付也在商超零售场景逐渐应用,很多的大型超市引进自助收银系统,实现自助结账应用。
已知某超市有自助收银机m台,每件商品扫码时间都相等,均为1秒,现有n个顾客准备结账,初始顺序已经确定为1-n,编号i号顾客购买的商品件数为ci,当其中某名顾客扫完所有商品后,下一名排队等候付款的顾客马上使用刚空闲的这台自助收银机,即忽略支付时间和自助收银机换人的时间开销,则所有顾客完成结账需要多少时间?
输入格式:
输入第一行为两个正整数n和m(1 ≤ n ≤ 10000,1 ≤m≤ 20),中间用一个空格隔开,分别表示待结账顾客人数和自助收银机台数。 第二行n个整数c1、c2、…、cn(1 ≤ci≤ 100),每两个整数之间用一个空格隔开,ci表示i号顾客购买的商品件数。
输出格式:
输出只有一个正整数,即所有顾客完成结账的总时间。
输入样例1:
5 3 4 4 1 2 1
输出样例1:
4
输入样例2:
8 4 23 71 87 32 70 93 80 76
输出样例2:
163
样例1说明:
第1秒,3名顾客扫码。第1秒结束时,1、2、3号顾客每人已扫码商品1件,3号顾客完成结账,4号顾客接替3号顾客开始扫码。第3秒结束时,1、2号顾客每人已扫码商品3件,4号顾客的已扫码商品2件。4号顾客完成结账,5号顾客接替4号顾客开始扫码。第4秒结束时,1、2号顾客每人已扫码商品4件,5号已扫码商品1件。1、2、5号完成结账,即所有人完成结账。总结账时间为4 秒。
分析
方法一:
用数组保存商品,开头位置当做收银机。每次循环,收银机位置数据自减。然后检查是否有数据为0,有的话后边数据前移补上。这里考虑到顾客数远大于收银机数,改变策略,让收银机位置后移。
方法二:
同样用数组保存商品,开头位置当做收银机。每次循环,收银机位置数据自减。用一个指针代表遍历剩余顾客。检查到有数据为0时,指针位置数据补上该位置,指针后移。
代码
方法一
#include<stdio.h>
int main()
{
int a,b,ti=0;
scanf("%d %d",&a,&b);
int arr[a];
for(int i=0;i<a; i++){
scanf("%d",&arr[i]);
}
for(int i=0; i<a; ){
for(int j=i;j<i+b&&j<a; j++){//自减
arr[j]-=1;
}
ti++;
for(int j=i; j<i+b&&j<a; j++){
if(arr[j]==0){
for(int k=j; k>i; k--){//收银机后移
arr[k]=arr[k-1];
}
i++;//收银机起始位置改变
}
}
}
printf("%d",ti);
return 0;
}
方法二
#include<stdio.h>
int main()
{
int a,b,ti=0;
scanf("%d %d",&a,&b);
int arr[a];
int num=b;//用下标代替指针
for(int i=0;i<a; i++){
scanf("%d",&arr[i]);
}
while(1){
int sta=0;
for(int j=0;j<b&&j<a; j++){
if(arr[j]!=0) arr[j]-=1;//防止出现负数
}
ti++;
for(int j=0; j<b&&j<a; j++){
if(arr[j]==0&&num<a){
arr[j]=arr[num++];
}
}
for(int j=0;j<b&&j<a; j++){//检查收银机是否同时都无人
if(arr[j]!=0){
sta=1;
break;
}
}
if(sta==0) break;
}
printf("%d",ti);
return 0;
}