首页 > 试题广场 >

Queueing at Bank (25)

[编程题]Queueing at Bank (25)
  • 热度指数:2700 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
Suppose a bank has K windows open for service. There is a yellow line in front of the windows which devides the waiting area into two parts. All the customers have to wait in line behind the yellow line, until it is his/her turn to be served and there is a window available. It is assumed that no window can be occupied by a single customer for more than 1 hour.
Now given the arriving time T and the processing time P of each customer, you are supposed to tell the average waiting time of all the customers.

输入描述:
Each input file contains one test case.  For each case, the first line contains 2 numbers: N (<=10000) - the total number of customers, and K (<=100) - the number of windows.  Then N lines follow, each contains 2 times: HH:MM:SS - the arriving time, and P - the processing time in minutes of a customer.  Here HH is in the range [00, 23], MM and SS are both in [00, 59].  It is assumed that no two customers arrives at the same time.
Notice that the bank opens from 08:00 to 17:00. Anyone arrives early will have to wait in line till 08:00, and anyone comes too late (at or after 17:00:01) will not be served nor counted into the average.


输出描述:
For each test case, print in one line the average waiting time of all the customers, in minutes and accurate up to 1 decimal place.
示例1

输入

7 3<br/>07:55:00 16<br/>17:00:01 2<br/>07:59:59 15<br/>08:01:00 60<br/>08:00:00 30<br/>08:00:02 2<br/>08:03:00 10

输出

8.2
package go.jacob.day922;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;

public class Demo2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt(), K = sc.nextInt();
        ArrayList<Customer> list = new ArrayList<Customer>();
        int[] windows = new int[K];
        // 记录等待时间
        int waitTime = 0;
        // 将17:0:0前到达的顾客存入list
        for (int i = 0; i < N; i++) {
            String time = sc.next();
            int needTime = sc.nextInt();
            // 说明超时到达
            if (time.compareTo("17:00:00") > 0)
                continue;
            String[] arr = time.split(":");
            int h = Integer.parseInt(arr[0]), m = Integer.parseInt(arr[1]), s = Integer.parseInt(arr[2]);
            int arriveTime = h * 3600 + m * 60 + s;
            if (arriveTime < 8 * 3600) {
                waitTime += 8 * 3600 - arriveTime;
            }
            list.add(new Customer(arriveTime, needTime));
        }
        // 按到达时间排序
        Collections.sort(list, new Comparator<Customer>() {
            @Override
            public int compare(Customer c1, Customer c2) {
                return c1.arriveTime - c2.arriveTime;
            }
        });
        for (int i = 0; i < list.size(); i++) {
            Customer c = list.get(i);
            int w = findFreeWindow(windows, c);
            // 找到空闲窗口
            if (w >= 0) {

                if (c.arriveTime < 8 * 3600) {
                    windows[w] = 8 * 3600 + c.needTime;
                } else {
                    windows[w] = c.arriveTime + c.needTime;
                }
            } else {// 不存在空闲窗口,顾客需要等待
                w = findFirstFreeWindow(windows);
                //因为之前waitTime已经加上相对8点的等待时间,所以这里必须判断
                if (c.arriveTime < 8 * 3600) {
                    waitTime += windows[w] - 8 * 3600;
                    windows[w] += c.needTime;
                } else {
                    waitTime += windows[w] - c.arriveTime;
                    windows[w] += c.needTime;
                }
            }
        }
        System.out.printf("%.1f", waitTime / 60.0 / list.size());
        sc.close();
    }

    private static int findFirstFreeWindow(int[] windows) {
        int first = 0;
        for (int i = 1; i < windows.length; i++) {
            if (windows[i] < windows[first])
                first = i;
        }
        return first;
    }

    // 试图找到当前顾客可以直接进入的窗口
    private static int findFreeWindow(int[] windows, Customer customer) {
        for (int i = 0; i < windows.length; i++) {
            if (windows[i] <= customer.arriveTime)
                return i;
        }
        return -1;
    }
}

class Customer {
    int arriveTime;
    int needTime;

    public Customer(int arriveTime, int needTime) {
        super();
        this.arriveTime = arriveTime;
        this.needTime = needTime * 60;
    }

}

发表于 2017-09-22 11:37:40 回复(0)
更多回答
遇到比较坑的地方(也是我自己忽视的地方,导致牛客网可以通过,pat只能过一半)
只有在17:01以及之后的顾客不计入人数,有些在这之前虽然没有被服务,也到计入其中

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <math.h>
#include <vector>
#include <map>
#include <queue>

using namespace std;
const int maxn = 10001;
const int maxw = 101;
const int INF = 0x3fffffff;
long long window[maxw];  //记录每个窗口当前已经服务的时间,(加上开始的时间8:00,就是每个窗口开始下一个服务的时间)
struct Customer{
    string arrive_time;
    int service_time;
};

Customer customers[maxn];

int ctoi(char c) {
    return (int)c -48;
}

int getTime(string time) {
    int hour = ctoi(time[0])*10 + ctoi(time[1]);
    int minute = ctoi(time[3])*10 + ctoi(time[4]);
    int second = ctoi(time[6])*10 + ctoi(time[7]);

    return hour*3600 + minute*60 + second;
}

bool cmp(Customer a, Customer b){
    return getTime(a.arrive_time)< getTime(b.arrive_time);
}

int main() {
    int open_time = 8*3600;
    int close_time = 17*3600+1;
    int n,k;
    int cnt = 0;
    scanf("%d %d", &n, &k);
    for(int i=0;i<n;i++){
        cin>>customers[i].arrive_time>>customers[i].service_time;
        if(customers[i].service_time>60){
            customers[i].service_time = 60;
        }

    }
    fill(window, window+k, 0);
    sort(customers, customers+n, cmp);

    int total_wait_time = 0;
    for(int i=0;i<n;i++){
        int temp = getTime(customers[i].arrive_time);
        if(temp >= close_time){ //用户到达的时间太晚,结束(因为到达时间已排好序,后面的肯定更晚)
            break;
        }
        cnt++;

        int min_time = INF, window_num = -1;
        for(int j=0;j<k;j++){  //找到最早空闲的窗口
            if(window[j] < min_time){
                min_time = window[j];
                window_num = j;
            }
        }

        if(temp < window[window_num]+open_time){  //如果用户到达时间在这之前,则需要等待
            total_wait_time += window[window_num] + open_time - temp;
            window[window_num] += customers[i].service_time * 60;
        }else{ //否则无需等待
            window[window_num] = customers[i].service_time * 60+temp - open_time;
        }

    }

    float ans = ((float)total_wait_time/60)/cnt;

    printf("%0.1f", ans);
}


发表于 2019-08-26 13:33:29 回复(0)
 9942 个样本的时候过不去????  样本只通过80% 后来发现是有一个地方少加了一个1
附 对数器 版本  调试大杀器,毕竟那么多人已经得到了答案
因为检查代码的时候总觉得没有问题可是牛客对于9000多个样本数据 也无法完全看到
还是对数器靠谱 
#include <iostream>
#include <fstream>
#include <string>
#include <string.h>
#include <algorithm>
#include <vector>

using namespace std;

int nCus, kWin;


#define STARTTIME 8*60*60
#define CLOSETIME 17*60*60
struct cus
{
    int comTim;
    int processSecond;
    int waitTime = 0;
};

int kWindows[101] = { 0 };
vector<struct cus> cusV;

bool Cmp(struct cus & a, struct cus &b)
{
    return a.comTim < b.comTim;
}

int CalTime(string t1)
{
    int hour, minutes, seconds;
    hour = minutes = seconds = 0;
    sscanf(t1.c_str(), "%d:%d:%d", &hour, &minutes, &seconds);
    return hour * 60 * 60 + minutes * 60 + seconds;
}


double CalWaitTime(vector<struct cus> & v)
{
    // 先初始化最开始的人开始在窗口上排成一排  8:00 以及 8:00 以前来到的人
    memset(kWindows, 0, sizeof(kWindows));
    int customer = 0;
    // 然后在离结束之前一直在处理
    for (int i = STARTTIME; customer < v.size(); i++)
    {
        for (int j = 0; j < kWin; j++)
        {
            if (kWindows[j] != 0)
            {// 有人正在处理
                kWindows[j]--;
                // 如果处理完了 看队列中数据是否还有
                if (kWindows[j] == 0)
                {
                    if (customer < v.size() && v[customer].comTim <= i)
                    {
                        v[customer].waitTime = i - v[customer].comTim + 1;// 刚开始一直没找到这里少加了一个1s
                        kWindows[j] = v[customer++].processSecond;
                    }
                }
            }
            else// 如果本来就没人排队 看下一个客户来临的时间是否到达,如果达到那么就开始处理
            {
                if (customer < v.size()&&v[customer].comTim <= i)
                {
                    v[customer].waitTime = i - v[customer].comTim;
                    kWindows[j] = v[customer].processSecond - 1;
                    customer++;
                }
            }
        }
    }
    // 开始计算 customer 个 客户的等待时间
    long long sum = 0;
    for (int i = 0; i < customer; i++)
    {
        sum += v[i].waitTime;
    }
    if (customer)
    {
        return sum*1.0 / (double)(60.0 * customer);
    }
    else
    {
        return 0.0;
    }
     
}

int main()
{
    //ifstream cin("test2.txt");
    while (cin >> nCus >> kWin)
    {
        cusV.clear();
        //cusV.resize(nCus);
        string comTim;
        int processSecond;
        int comTime;
        for (int i = 0; i < nCus; i++) // 从第一个开始算
        {
            cin >> comTim >> processSecond;
            if (CalTime(comTim) > CLOSETIME)
            {
                continue;
            }
            else
            {
                struct cus *p = new struct cus;
                p->comTim = CalTime(comTim);
                if (processSecond > 60) processSecond = 60;
                p->processSecond = processSecond * 60;
                cusV.push_back(*p);
            }
        }
        
        sort(cusV.begin(), cusV.end(), Cmp);
        printf("%.1lf\n", CalWaitTime(cusV));
        // 计算等待的总共分钟数
    }
    system("pause");
}



#include <iostream>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <windows.h>
#include <string>



#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;


int random(int a, int b) // 生成 [a,b] 之间的随机数 
{
    return rand()%(b-a+1)+a;
}

string AddZero(int x)
{
    string rlt;
    if(x <= 9)
    {
        rlt = "0";
        rlt += x + '0';
    }
    else
    {
        rlt = x / 10 + '0';
        rlt += x % 10 + '0'; 
    }
    return rlt;
}

bool GenData(void) // 生成器 
{
        ofstream ofile;
        ofile.open("c:\\Users\\leon\\OneDrive\\Documents\\Test\\DEV_C++\\Proj10_9\\case.txt", ios::out ); //| ios::app | ios::trunc 为输出(写)而打开文件 所有输出附加在文件末尾  
        if(!ofile.is_open())
        {
            cout << "ofile文件打开失败" << endl; 
            return 0;
        }
        int N = random(1, 10000);
        int K = random(1, 100);
        ofile << N << " " << K << endl;
        int hour,minute,second,process;
        for(int i=0; i<N; i++)
        {
            hour = random(0, 23);
            minute = random(0, 59);
            second = random(0, 59);
            process = random(0, 60);
            ofile << AddZero(hour) << ":" << AddZero(minute) << ":" << AddZero(second) << " " << process << endl;
        }
                
        ofile.close();
        Sleep(10);
        return true;
}
int result1,result2;
// --------------------------------------------------------------------------------------------- 
int nCus, kWin;

#define STARTTIME 8*60*60
#define CLOSETIME 17*60*60
struct cus
{
    int comTim;
    int processSecond;
    int waitTime = 0;
};

int kWindows[101] = { 0 };
vector<struct cus> cusV;

bool Cmp(struct cus & a, struct cus &b)
{
    return a.comTim < b.comTim;
}

int CalTime(string t1)
{
    int hour, minutes, seconds;
    hour = minutes = seconds = 0;
    sscanf(t1.c_str(), "%d:%d:%d", &hour, &minutes, &seconds);
    return hour * 60 * 60 + minutes * 60 + seconds;
}


double CalWaitTime(vector<struct cus> & v)
{
    // 先初始化最开始的人开始在窗口上排成一排  8:00 以及 8:00 以前来到的人
    memset(kWindows, 0, sizeof(kWindows));
    int customer = 0;
    // 然后在离结束之前一直在处理
    for (int i = STARTTIME; customer < v.size(); i++)
    {
        for (int j = 0; j < kWin; j++)
        {
            if (kWindows[j] != 0)
            {// 有人正在处理
                kWindows[j]--;
                // 如果处理完了 看队列中数据是否还有
                if (kWindows[j] == 0)
                {
                    if (customer < v.size() && v[customer].comTim <= i)
                    {
                        v[customer].waitTime = i - v[customer].comTim+1;
                        kWindows[j] = v[customer++].processSecond;
                    }
                }
            }
            else// 如果本来就没人排队 看下一个客户来临的时间是否到达,如果达到那么就开始处理
            {
                if (customer < v.size() && v[customer].comTim <= i)
                {
                    v[customer].waitTime = i - v[customer].comTim;
                    kWindows[j] = v[customer].processSecond - 1;
                    customer++;
                }
            }
        }
    }
    // 开始计算 customer 个 客户的等待时间
    long long sum = 0;
    for (int i = 0; i < customer; i++)
    {
        sum += v[i].waitTime;
    }
    cout << "sum" << sum << endl;
    result1 = sum; 
    if (customer)
    {
        return sum*1.0 / (double)(60.0 * customer);
    }
    else
    {
        return 0.0;
    }
     
}

double EXE1(void)
{
    ifstream cin("case.txt");
    while (cin >> nCus >> kWin)
    {
        cusV.clear();
        //cusV.resize(nCus);
        string comTim;
        int processSecond;
        int comTime;
        for (int i = 0; i < nCus; i++) // 从第一个开始算
        {
            cin >> comTim >> processSecond;
            if (CalTime(comTim) > CLOSETIME)
            {
                continue;
            }
            else
            {
                struct cus *p = new struct cus;
                p->comTim = CalTime(comTim);
                if (processSecond > 60) processSecond = 60;
                p->processSecond = processSecond * 60;
                cusV.push_back(*p);
            }
        }
        
        sort(cusV.begin(), cusV.end(), Cmp);
        printf("%.1lf\n", CalWaitTime(cusV));
    }
    cin.close();
    Sleep(10); 
    return result1;
}

double EXE2(void)
{
    int N, K;
    int P[10000];
    //ifstream cin("case.txt");
    freopen("case.txt","r",stdin);
    scanf("%d %d", &N, &K);
    for (int i = 0; i < N; i++)
    {
        int h, m, s, p;
        scanf("%d:%d:%d %d", &h, &m, &s, &p);
        cout << h << " " << m << endl;
        if (p > 60)
            p = 60;
        P[i] = ((h * 3600 + m * 60 + s) << 12) + p * 60;
    }
    sort(P, P + N);
    int W[K];
    for (int i = 0; i < K; i++)
    {
        W[i] = 8 * 3600;
    }
    int sum, count;
    sum = 0;
    for (count = 0; count < N; count++)
    {
        if ((P[count] >> 12) > 17 * 3600)
            break;
        int min = 0;
        for (int i = 1; i < K; i++)
        {
            if (W[min] > W[i])
                min = i;
        }
        int wait = W[min] - (P[count] >> 12);
        if (wait >= 0)
        {
            sum += wait;
            W[min] += (P[count] & 0xFFF);
        }
        else
        {
            W[min] = (P[count] >> 12) + (P[count] & 0xFFF);
        }
    }
    result2 = sum;
    if (count != 0)
    {
        printf("%.1f\n", sum / 60.0 / count);
        cout << "sum" << sum << endl;
    }
    else
    {
        printf("0.01\n");
    }
    //cin.close();
    Sleep(10); 
    return result2;
}
int main()
{
    for(int i=0; i<100000; i++) // 比较 100000 次 
    {
        if(GenData())
        {
            cout << "生成器生成数据成功" << endl;
        }
        // 执行两个程序
        cout << endl <<"开始执行1" << endl;
        EXE1();
        cout << endl << "执行结束1" << endl << "开始执行2" << endl;
        EXE2(); 
        cout << endl << "执行结束2" << endl;
        // 开始比较数据 
        if(result1 != result2)
        {
            cout << "数据不相等 " <<  result1 << " " << result2 << endl;
            break; 
        }
        cout<< "第 " << i  << " 次执行" << endl; 
    }

    system("pause");
}

编辑于 2018-08-24 15:52:59 回复(0)
/**
1.把到达、处理、等待的时间全部使用秒来计算。
*/
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 10001

struct People{
    int arriveTime;
    int process;//需要处理的时间
    int wait ;//等待的时间
};

vector<People> qu;//将人加入到队列中

bool cmp(People p1,People p2){
    return p1.arriveTime < p2.arriveTime;
}


int main(){
    int num,winNum;//总人数  总窗口数
    int i;
    People tempPeo;//暂存人的信息
    scanf("%d %d",&num,&winNum);
    int hour,minute,second,process;//时 分 秒
    int boundary = 17 * 60 * 60 ;//17:00:00
    int count = 0;
    int window[maxn] ;//存放的是当前窗口的时间
    int startTime = 8 * 60 * 60;//开始时间
    
    for(i = 0;i<num;i++){
        scanf("%d:%d:%d %d",&hour,&minute,&second,&process);//输入每个人的信息
        tempPeo.arriveTime = hour*60*60 + minute * 60 + second;        
        tempPeo.process = process * 60;
        tempPeo.wait = 0;//等待时间初始化为0
        if(tempPeo.arriveTime < boundary){
            qu.push_back(tempPeo);//将每个人的信息入队
            count ++;
        }
    }
    sort(qu.begin(),qu.end(),cmp);    
    for(i = 0;i < winNum;i++ ){//按照窗口数  进行初始化
        window[i] = startTime;
    }

    double wait = 0;
    int minStart;//找一个最小开始时间 去服务
    int index ;//最小开始时间的下标
    //开始处理任务
    while(!qu.empty()){//假设还有剩余人数未服务
        minStart = 9999999;
        for(i = 0;i < winNum ;i++){//找第一个可以服务的窗口
            if(window[i] < minStart){
                minStart = window[i];
                index = i;
            }
        }
        tempPeo = qu[0];
        qu.erase(qu.begin());//删除头
        if(tempPeo.arriveTime < window[index]){//如果先到  窗口还未开启
            wait += (window[index] - tempPeo.arriveTime);
        }    
        window[index] += tempPeo.process;//更新时间
    }
    double avg = ( wait / 60) / count;
    printf("%.1lf",avg);
}
/**
7 3
07:55:00 16
17:00:01 2
07:59:59 15
08:01:00 60
08:00:00 30
08:00:02 2
08:03:00 10

2 1
07:55:00 16
17:00:01 2

2 2
08:00:00 16
07:58:00 2
*/
发表于 2018-01-18 23:32:55 回复(1)
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#pragma warning(disable:4996);
struct cus {
    int stamp, waiting, occu; //到来的时间,等待服务的时间,占用窗口时长
};

vector <cus> q;

int n, k;
int win[101]; //记录窗口时间
double total=0;
bool cmp(cus a, cus b) { //按照先到的顺序排序
    return a.stamp < b.stamp;
}

int main() {
#if ONLINE_JUDGE
#else
    freopen("input.txt", "r", stdin);
#endif
    cin >> n >> k;
    int h, m, s, o, cnt = 0;
    for (int i = 0; i < n; i++) {
        scanf("%d:%d:%d %d", &h, &m, &s, &o);
        if (h * 3600 + m * 60 + s < 17 * 3600 + 1) { //符合条件的记录算进去
            cus c;
            c.stamp = h * 3600 + m * 60 + s;
            c.occu = o * 60;
            q.push_back(c);
        }
    }
    for (int i = 0; i < k; i++) { //窗口时间初始化
        win[i] = 8 * 3600;
    }
    sort(q.begin(), q.end(), cmp);
    for (int i = 0; i < q.size();i++) {
        cus c = q[i];
        int mintim = *min_element(win, win + k); //获取最早结束的窗口时间
        //mintim = mintim < 17 * 3600 ? mintim : 17 * 3600; //结束时间要小于窗口关闭时间
        int tmp = c.stamp < mintim ? (mintim - c.stamp) : 0; //获得用户需要等待的时间
        mintim=mintim>c.stamp?mintim:c.stamp;
                *min_element(win, win + k) = mintim + c.occu;
        c.waiting = tmp;
        total += tmp;
    }
    double res = total / 60 / q.size();
    printf("%.1lf", res);
}

编辑于 2021-08-04 22:57:10 回复(0)
短小又精悍!!!!
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
struct node{
	int hh,mm,ss,op,toally;
	node(int hh,int mm,int ss,int op,int toally):hh(hh),mm(mm),ss(ss),op(op),toally(toally){}
};
int n,k,hh,mm,ss,op,opentime=8*3600,closetime=17*3600,cnt=0,ans=0;
bool cmp(node a,node b){return a.toally<b.toally;}
int main(){
	scanf("%d%d", &n, &k);
	vector<node> open;
	vector<int> windows(k,opentime);
	for(int i=0;i<n;i++){
		scanf("%d:%d:%d %d",&hh,&mm,&ss, &op);
		open.push_back(node(hh,mm,ss,op*60,hh*3600+mm*60+ss));
	}
	sort(open.begin(),open.end(),cmp);
	for(int i=0;i<n;i++){
		int Max=0x3fffffff,flag;
		for(int j=0;j<k;j++)
			if(windows[j]<Max){
				Max=windows[j];
				flag=j;
			}
		if(open[i].toally<=closetime){
			cnt++;//有效人数+1
			open[i].toally<windows[flag]? ans+=(windows[flag]-open[i].toally):windows[flag]=open[i].toally;
			open[i].op>3600 ? windows[flag]+=3600 : windows[flag]+=open[i].op;
		}
	}
    printf("%.1f",ans*1.0/(cnt*60));
	return 0;
}

发表于 2021-01-28 10:15:20 回复(0)
过了80%。不模拟每一秒是我最后的倔强~
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<bits/stdc++.h>

#define INF 2147483647
#define MIN INF+1
#define ll long long

using namespace std;

struct cus {
	int h, m, s;
	int timestamp = 0;
	int service_time = -1;
	int duration = -1;
	int od = -1;
};

bool cmp(cus c1, cus c2) {
	return c1.timestamp < c2.timestamp;
}

int N, K;
queue<int> bank_wait;
int windows[105];
double now = 8 * 3600;
int empty_win = 0;

// 获得一个空闲位置,并占用之 
int get_window(int cus) {
	for(int i = 0; i < K; i++) {
		if(windows[i] == -1) {
			windows[i] = cus;
			empty_win--;
			return i;
		}
	}
	return -1;
}

int main() {    
	// std::ios::sync_with_stdio(false);
    // std::cin.tie(0);
    
	cin >> N >> K;
	empty_win = K;
	cus c[N];
	for(int i = 0; i < N; i++) {
		int h, m, s;
		scanf("%d:%d:%d", &h, &m, &s);
		int duration;
		cin >> duration;
		c[i].timestamp = h*3600 + m*60 + s;
		c[i].h = h;
		c[i].m = m;
		c[i].s = s;
		if(duration > 3600)
			duration = 3600;
		c[i].duration = duration*60;
		c[i].od = duration*60;
	}
	
	// It is assumed that no two customers arrives at the same time.
	// 按到达时间排序 
	sort(c, c + N, cmp);
	
	now = 8 * 3600;
	for(int i = 0; i < K; i++)
		windows[i] = -1;

	for(int i = 0; i < N; i++) {
		cout << c[i].timestamp - 8*3600 << endl;
		bank_wait.push(i);
	}
	
	while(!bank_wait.empty()) {
		
		
		int min_time = INF;
		for(int i = 0; i < K; i++) {
			if(windows[i] != -1) {
				if(c[windows[i]].duration < min_time) {
					min_time = c[windows[i]].duration;
				}
			}
		}
		
		// cout << c[bank_wait.front()].timestamp << ' ' << c[bank_wait.front()].timestamp - (min_time+now) << endl;
		
		if(c[bank_wait.front()].timestamp < min_time + now || empty_win != 0) {		// 新顾客先来了
			if(c[bank_wait.front()].timestamp > 17*3600)
				break;
			int new_cus = bank_wait.front();
			int window = get_window(new_cus);
			if(window != -1) {		//有空闲 
				bank_wait.pop();
				if(c[new_cus].timestamp > now) {
					now = c[new_cus].timestamp;
				}
				c[new_cus].service_time = now;
			} else {				// 无空闲 
				//cout << bank_wait.empty() << endl;
				for(int i = 0; i < K; i++) {
					c[windows[i]].duration -= min_time;
					if(c[windows[i]].duration == 0) {		// 服务完成,腾退窗口 
						windows[i] = -1;
						empty_win++;
					}
				}
				now += min_time;
				// 必定有空位 出等待区,插入 
				int tmp = get_window(new_cus);
				bank_wait.pop();
				if(c[new_cus].timestamp > now) {
					now = c[new_cus].timestamp;
				}
				c[new_cus].service_time = now;
			}  
		} else {	// 正在办事的顾客比下一个来的顾客先完事 
			for(int i = 0; i < K; i++) {
				if(windows[i] == -1)
					continue; 
				c[windows[i]].duration -= min_time;
				if(c[windows[i]].duration == 0) {		// 服务完成,腾退窗口 
					empty_win++;
					windows[i] = -1;
				}
			}
			now += min_time;
		} 
	}
	
	// 统计
	double sum = 0.0;
	int i = 0;
	for(; i < N; i++) {
		if(c[i].timestamp > 17*3600)
			break;
		// cout << c[i].service_time - 8*3600 << ' ' << c[i].timestamp - 8*3600 << endl;
		sum += c[i].service_time - c[i].timestamp;
	} 
	sum = (sum / 60) / (double)i;
	printf("%.1f", sum);
	return 0;
}


发表于 2020-09-18 10:19:56 回复(0)
这题的意思是,只要是当天下午17:00前来的客人就一定得接待,哪怕窗口都很忙排队排到明天后天也要把客人接待。
#include<stdio.h>

typedef struct{
	int ct,pt,wt;//cometime,processingtime,waittime
}cus;

int N,K,time,window[100],cursor=0;
cus a[10000];

int Comp(const void*x,const void*y)
{	return ((cus*)x)->ct-((cus*)y)->ct;
}

int main()
{
	int i,j,H,M,S,p,busy,sum=0;
	scanf("%d %d",&N,&K);
	for(i=0,j=0;i<N;i++){
		scanf("%d:%d:%d %d",&H,&M,&S,&p);
		if(H*3600+M*60+S<=61200){
			a[j].ct=H*3600+M*60+S;
			a[j++].pt=p*60<3600?p*60:3600;
		}
	}//录入信息,对于迟于17点的直接不予录入
	qsort(a,j,sizeof(cus),Comp);//根据cometime排序
	for(i=0;i<K;i++)window[i]=-1;//所有窗口初始值置为空闲
	for(time=28800;time<=61200||busy;time++){
		busy=0;
		for(i=0;i<K;i++){
			if(window[i]>=0){
				busy=1;
				if(!--a[window[i]].pt)window[i]=-1;//当processingtime减到0时,该顾客退出窗口
			}
		}
		for(i=0;i<K&&cursor<j&&a[cursor].ct<=time;i++){//遍历窗口
			if(window[i]<0){//若空闲,推入顾客
				a[cursor].wt=time-a[cursor].ct;
				sum+=a[cursor].wt;
				window[i]=cursor++;
			}
		}
	}
	printf("%.1lf",sum/60.0/j);
}


发表于 2019-12-29 10:35:36 回复(0)
我也是佛了,请问就算是在下午五点之前到也可以赖到明早不走吗
发表于 2019-09-07 01:17:13 回复(0)
PAT上就差一个点过不了,实在看不出问题在哪,求大家帮忙看看。 #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int maxn = 10010; const int maxk = 101; struct person{//个人信息 int hh,mm,ss;//到达时间 int on_time, off_time;//达到时间,离开时间(相对时间) int waiting_time = 0; int p;//服务时常(<=60) }per[maxn]; int N, K; int windows[maxk];//每个窗口的服务结束时间 int find_window(){//选择窗口 int MIN = (17 - 8) * 60*60 + 10, u = -1; for (int i = 0; i < K;++i){ if(windows[i]<MIN){
MIN = windows[i];
u = i;
}
} return u;
} double simulate(int count){//进行排队模拟 for (int i = 0; i < 3;++i){
per[i].waiting_time += 0; //开门后直接开始,不需额外等待 per[i].off_time = per[i].on_time + per[i].p;
windows[i] = per[i].off_time;
} for (int i = 3; i < count;++i){ int w = find_window();//选泽窗口 if(per[i].on_time>windows[w]){ //来的时候窗口有空位 per[i].waiting_time = 0;//不需要等待 per[i].off_time = per[i].on_time + per[i].p;
windows[w] = per[i].off_time;
} else{
per[i].waiting_time = windows[w]-per[i].on_time;
per[i].off_time = windows[w] + per[i].p;
windows[w] = per[i].off_time;
}
} int sum = 0; for(int i = 0; i < count;++i){
sum += per[i].waiting_time;
} double ave; return ave = sum / count/60.0000;
} bool cmp(person a,person b){ if(a.hh!=b.hh){ return a.hh < b.hh;
}else{ if(a.mm!=b.mm){ return a.mm < b.mm;
}else{ return a.ss < b.ss;
}
}
} int main(){
cin >> N >> K; if(N==0){
printf("0.0"); return 0;
} int count = N; for (int i = 0; i < N;++i){
scanf("%d:%d:%d %d", &per[i].hh, &per[i].mm, &per[i].ss, &per[i].p);
per[i].p *= 60;//变成秒 per[i].on_time = (per[i].hh-8)*3600 + per[i].mm * 60 + per[i].ss;
}
sort(per,per+N,cmp); for(int i = 0; i < N;++i){ if(per[i].hh<8){
per[i].on_time = 0;//8点前来的当作8点来 per[i].waiting_time=(8-per[i].hh) * 3600 - per[i].mm * 60 - per[i].ss; //提前来的人等待时间特殊处理 } else if(per[i].on_time>(17-8)*3600)
count--;//将晚来的直接舍掉 } double ave=simulate(count);
printf("%.1f", ave); return 0;
}
发表于 2019-07-30 22:24:11 回复(0)
什么鬼啊,这里全部过了,pat那边一半都过不了,心态崩了
#include<iostream>
#include<fstream>
#include<algorithm>
#include<string>
#include<stdio.h>
using namespace std;
struct Time
{
    int h,m,s;
    Time(int h=0,int m=0,int s=0)
    {
        this->h=h;
        this->m=m;
        this->s=s;
    }
    Time(string st)
    {
        h=(st[0]-'0')*10+st[1]-'0';
        m=(st[3]-'0')*10+st[4]-'0';
        s=(st[6]-'0')*10+st[7]-'0';
    }
};
Time operator+ (Time t1,Time t2)
{
    int carry;
    Time result;
    result.s=t1.s+t2.s;
    carry=result.s/60;
    result.s%=60;
    result.m=t1.m+t2.m+carry;
    carry=result.m/60;
    result.m%=60;
    result.h=t1.h+t2.h+carry;
    return result;
}
bool operator<(Time t1,Time t2)
{
    if(t1.h!=t2.h)
        return t1.h<t2.h;
    else if(t1.m!=t2.m)
        return t1.m<t2.m;
    else return t1.s<t2.s;
}
bool operator>(Time t1,Time t2)
{
    if(t1.h!=t2.h)
        return t1.h>t2.h;
    else if(t1.m!=t2.m)
        return t1.m>t2.m;
    else return t1.s>t2.s;
}
double operator-(Time t1,Time t2)
{
    double m1,m2;
    m1=t1.h*60+t1.m+(double)t1.s/60;
    m2=t2.h*60+t2.m+(double)t2.s/60;
    double waitTime=m1-m2>=0? m1-m2:0;
    return waitTime;
}
int numC;
int numW;
struct Customer
{
    Time arriTime;
    Time serveTime;
    int processTime;
    double waitTime;
}customers[10010];
bool cmpArri(Customer c1,Customer c2)
{
    return c1.arriTime<c2.arriTime;
}
Time windowEndTime[110];
void serve(Customer &c)
{
    //找到一个最先结束的window
    Time min=Time(1000,0,0);
    int minIndex=0;
    for(int i=0;i<numW;i++)
    {
        if(windowEndTime[i]<min)
        {
            min=windowEndTime[i];
            minIndex=i;
        }
    }
    c.serveTime=windowEndTime[minIndex];
    windowEndTime[minIndex]=c.serveTime+Time(0,c.processTime,0);
    c.waitTime=c.serveTime-c.arriTime;
}
int main()
{
    cin>>numC>>numW;
    fill(windowEndTime,windowEndTime+numW,Time(8,0,0));
    for(int i=0;i<numC;i++)
    {
        string s;
        int a;
        cin>>s>>a;
        customers[i].arriTime=Time(s);
        if (a<60)
        {
            customers[i].processTime=a; 
        }
        else customers[i].processTime=60;
    }
    //生成队列
    sort(customers,customers+numC,cmpArri);
    for(int i=0;i<numC;i++)
    {
        serve(customers[i]);
    }
    int num=0;
    double total=0;
    for(int i=0;i<numC;i++)
    {
        if(customers[i].arriTime<Time(17,0,1))
        {
            total+=customers[i].waitTime;
            num++;
        }
    }
    if (num!=0)
    {
        printf("%.1f",total/num); 
    }
    else cout<<0;
    system("pause");
    return 0;
}


发表于 2019-02-09 16:35:50 回复(0)
//1017. Queueing at Bank (25)
#include <bits/stdc++.h>
using namespace std;
struct customer
{
int hh;
int mm;
int ss;
int pt;
// customer(int h,int m,int s,int p){hh = h,mm=m,ss = s,pt = p;};
int st;
int sst;
} customers[10005];

vector<int> res(10005);
bool cmp(customer a, customer b)
{
if (a.hh != b.hh)
return a.hh < b.hh;
else if (a.mm != b.mm)
return a.mm < b.mm;
else
return a.ss < b.ss;
}
queue<customer> q;
int main()
{
int N, K;
cin >> N >> K;
int h, m, s, p;
vector<int> server(K + 1, 0);
for (int i = 1; i <= N; i++)
{
customer tmp;
scanf("%02d:%02d:%02d %d", &tmp.hh, &tmp.mm, &tmp.ss, &tmp.pt);
tmp.st = tmp.hh * 60 * 60 + tmp.mm * 60 + tmp.ss;
customers[i] = tmp;
}
sort(customers + 1, customers + 1 + N, cmp);
// for (int i = 1; i <= N; i++)
// {
// cout << customers[i].hh << " " << customers[i].mm << " " << customers[i].pt << '\n';
// }
double sumt = 0;
int countc = 1;
int countq = 0;
double compc = 0;
int indext = 0;
for (indext = 1; indext <= N; indext++){
if(customers[indext].st>17*3600)break;
}
//cout<<indext<<'\n';
for (int t = 0 + 8 * 60 * 60; t <= 10*540*60+8*60*60,compc<indext-1; t++)
{
for (int i = 1; i <= K; i++) //出队
{
if (res[server[i]] == t)
{
server[i] = 0;
countq--;
}
}

while (countc <= N && countq < K && customers[countc].st <= t) //入队
{


customers[countc].sst = t;
sumt += double(t - customers[countc].st) / 60;
compc++;

int index = 1;
for (index; index <= K; index++)
{
if (server[index] == 0)
break;
}

res[countc] = customers[countc].sst + customers[countc].pt * 60;
server[index] = countc;
countq++;
countc++;
}
}
printf("%.1f", sumt / compc);
//printf("%.1f", compc);
}
发表于 2018-04-16 14:09:45 回复(0)

感觉和1016差不多, 就模拟一下几个队列, 有空位立即插入并计算等待时间, 没空位计算最早处理完的用户的离去时间,并更新为当前时间等等。

#include <iostream>
#include <queue>
#include <vector>
#include <cstdio>
#include <iomanip>
#include <algorithm>
using namespace std;

struct record
{
    int arrive_time;
    int process_time;
};
vector<queue<int>> my_ques;
vector<record> arrive_times;
vector<int> finish_times;

bool cmp(const record &a, const record &b) {
    return a.arrive_time < b.arrive_time;
}

int main()
{
    int customer_n, window_n;
    cin >> customer_n >> window_n;
    my_ques.resize(window_n);
    finish_times.resize(customer_n);
    int hour, minute, second, process_t;
    for (int i = 0; i < customer_n; i++) {
        scanf("%d:%d:%d", &hour, &minute, &second);
        cin >> process_t;
        record temp;
        temp.arrive_time = hour * 60 * 60 + minute * 60 + second;
        temp.process_time = process_t;
        arrive_times.push_back(temp);
    }
    sort(arrive_times.begin(), arrive_times.end(), cmp);
    int index = 0;
    int cur_serve = 0;
    int cur_time = 8 * 60 * 60;
    int total_waiting_time = 0;
    int toatl_served_cus = 0;
    while (index < arrive_times.size()) {
        if (cur_serve < window_n) {
            for (int i = 0; i < my_ques.size(); i++) {
                if (my_ques[i].empty()) {
                    my_ques[i].push(index);
                    break;
                }
            }
            if ((cur_time - arrive_times[index].arrive_time) > 0) {
                finish_times[index] = cur_time + arrive_times[index].process_time * 60;
                total_waiting_time += cur_time - arrive_times[index].arrive_time;
            }
            else {
                finish_times[index] = arrive_times[index].arrive_time + arrive_times[index].process_time * 60;
            }
            cur_serve++;
            index++;
            toatl_served_cus++;
        }
        else {
            cur_time = finish_times[my_ques[0].front()];
            for (int i = 0; i < my_ques.size(); i++) {
                if (finish_times[my_ques[i].front()] < cur_time) {
                    cur_time = finish_times[my_ques[i].front()];
                }
            }
            for (int i = 0; i < my_ques.size(); i++) {
                if (finish_times[my_ques[i].front()] == cur_time) {
                    my_ques[i].pop();
                    cur_serve--;
                }
            }
        }
        if (arrive_times[index].arrive_time > 17 * 60 * 60)
            break;
    }
    cout.setf(ios::fixed);
    cout << setprecision(1) << total_waiting_time * 1.0 / (60 * toatl_served_cus) << endl;

    return 0;
}
发表于 2018-02-12 10:42:11 回复(0)
// 银行排队问题
// 模拟队列
// 两种情况
//        1. 如果有空闲窗口,直接处理客户业务;
//        2. 否则,等待最先处理完毕的窗口。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

#ifdef ONLINE_JUDGE
#else
#include <fstream>
#endif

using namespace std;

struct Time
{
    int hour;
    int min;
    int sec;
};

struct Customer
{
    int arrival;
    int waittime;
};

int tos(const Time a)
{
    return (a.hour * 3600 + a.min * 60 + a.sec);
}

bool cmp(const Customer & a, const Customer & b)
{
    return a.arrival < b.arrival;
}

int main()
{
#ifdef ONLINE_JUDGE
#else
    ifstream cin("case.txt");
#endif // ONLINE_JUDGE

    int n, w;
    cin >> n >> w;

    // input customers' time arived
    vector<Customer>customer;
    Customer cus;
    Time time;
    char c;
    const int noserver = 17 * 3600;
    for (int i = 0;i < n;++i)
    {
        cin >> time.hour >> c >> time.min >> c >> time.sec >> cus.waittime;
        // 筛选数据
        cus.arrival = tos(time);
        cus.waittime *= 60;
        if (tos(time) < noserver)
        {
            customer.push_back(cus);
        }
    }

    sort(customer.begin(), customer.end(), cmp);
    
    //窗口时间线
    vector<int>windows;
    const int starttime = 8 * 3600;
    for (int i = 0;i < w;++i)
    {
        windows.push_back(starttime);
    }

    // 处理逻辑
    double sum = 0;
    n = customer.size();
    for (int i = 0;i < n;++i)
    {
        int min = 10000001;
        int index = 0;
        int j = 0;
        for (;j < w;++j)
        {
            if (customer[i].arrival >= windows[j])
            {
                windows[j] = customer[i].arrival + customer[i].waittime;
                break;
            }
            else
            {
                if (windows[j] < min)
                {
                    min = windows[j];
                    index = j;
                }
            }
        }
        if (j == w)
        {
            sum += min - customer[i].arrival;
            windows[index] += customer[i].waittime;
        }
    }
    
    // 秒数转分钟
    sum = (sum * 1.0 / 60 ) / n;
    printf("%.1lf\n", sum);
    getchar();
    return 0;
}

发表于 2017-12-01 17:31:39 回复(0)
啥头像
用时间线的方法,逐个处理,模拟显示生活中的处理方法:
import Queue

class Customer:
    def __init__(self, arrivingTime, processingTime, idx):
        self.arrivingTime = arrivingTime
        self.processingTime = processingTime
        self.idx = idx
        self.waitingTime = 0

class TimeUnit:
    def __init__(self, time, isCustomer, idx=0):
        self.time = time
        self.isCustomer = isCustomer
        self.idx = idx
    def __cmp__(self, other):
        return cmp(self.time, other.time)

N, K = map(int, raw_input().strip().split())
customers = []
timeLine = Queue.PriorityQueue()
startTime = 8*3600; endTime = 17*3600
idx = 0
for i in range(N):
    time, processingTime = raw_input().strip().split()
    time = map(int, time.split(':'))
    arrivingTime = time[0]*3600 + time[1]*60 + time[2]
    if arrivingTime <= endTime:
        processingTime = int(processingTime)*60
        customers.append(Customer(arrivingTime, processingTime, idx))
        timeLine.put(TimeUnit(arrivingTime, True, idx))
        idx = idx + 1
waitingList = []
i = 0; k = 0
N = len(customers)
while k<K:
    timeLine.put(TimeUnit(startTime, False))
    k = k + 1
while i<N:
    item = timeLine.get()
    if item.isCustomer:
        if k<K:
            k = k + 1
            customers[item.idx].waitingTime = item.time - customers[item.idx].arrivingTime
            i = i + 1
            timeLine.put(TimeUnit(item.time+customers[item.idx].processingTime, False))
        else:
            waitingList.append(item.idx)
    else:
        if waitingList:
            idx = waitingList.pop(0)
            customers[idx].waitingTime = item.time - customers[idx].arrivingTime
            i = i + 1
            timeLine.put(TimeUnit(item.time+customers[idx].processingTime, False))
        else:
            k = k - 1
sumTime = 0
for item in customers:
    sumTime = sumTime + item.waitingTime
print '%.1f' % (sumTime/(N*60.0))



编辑于 2016-02-26 22:35:10 回复(0)

问题信息

难度:
15条回答 5109浏览

热门推荐

通过挑战的用户

Queueing at Bank (25)