第一个思路就是模拟,每次模拟时间加一秒。但写出来发现太麻烦了。细节太多,结果错了也找不到错误的地方。。。。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <queue>
using namespace std;
struct Custom
{
int h,m,s;
int t;
bool isActive;
};
Custom *custom;
int N,W,num;
vector<Custom> c;
vector<Custom>::iterator it;
int wait;
Custom time;
int window_num;
bool cmp(Custom c1,Custom c2)
{
if(c1.h == c2.h)
{
if(c1.m == c2.m)
{
return c1.s < c2.s;
}
return c1.m < c2.m;
}
return c1.h < c2.h;
}
void InsertCustomer()
{
if(time.h == custom[num].h && time.m == custom[num].m && time.s == custom[num].s)
{
c.push_back(custom[num]);
num++;
return;
}
return;
}
void Action()
{
while(!c.empty() || num<N)
{
//运转时间
time.s++;
if(time.s == 60)
{
time.s = 0;
time.m++;
if(time.m == 60)
{
time.m = 0;
time.h++;
}
}
//8点前一直等待
if(time.h<8 || (time.h==8 && time.m ==0 && time.s==0))
{
if(num<N)
{
InsertCustomer();
wait--;
}
for(it = c.begin(); it != c.end(); it++)
{
if(!((*it).isActive))
{
wait++;
}
}
continue;
}
//8点以后视窗口情况
if(window_num == 0)
{
if(num<N)
{
InsertCustomer();
}
for(it = c.begin(); it != c.end(); it++)
{
if(!((*it).isActive))
{
wait++;
}else
{
(*it).t--;
if((*it).t == 0)
{
c.erase(it);
printf("%d %d %d\n",time.h,time.m,time.s);
it--;
window_num++;
}
}
}
}
else
{
if(num<N)
{
InsertCustomer();
}
for(it = c.begin(); it != c.end(); it++)
{
if((*it).isActive)
{
(*it).t--;
if((*it).t == 0)
{
c.erase(it);
it--;
window_num++;
}
}else
{
(*it).isActive = true;
(*it).t--;
window_num--;
}
}
}
}
}
int main()
{
int tempN;
scanf("%d %d",&tempN,&W);
N = tempN;
custom = new Custom[N];
window_num = W;
num = 1; //从第二个顾客开始对比时间
for(int i = 0;i<tempN;i++)
{
scanf("%d:%d:%d %d",&custom[i].h,&custom[i].m,&custom[i].s,&custom[i].t);
custom[i].t *= 60;
if(custom[i].h >=17)
{
N--;
}
}
sort(custom,custom+tempN,cmp);
time.h = custom[0].h;
time.m = custom[0].m;
time.s = custom[0].s;
c.push_back(custom[0]);
Action();
float ave = 0;
ave = (wait/tempN)/60.0;
printf("%.1f",ave);
return 0;
}
写的过程中遇到的知识疏漏:vector的iterator迭代器,只能用it != c.end() 判断是否到结尾,不能用it < c.end()。
且在迭代过程中调用了erase函数的话,需要立刻把迭代器指针-1,因为erase返回的指针就是指向被擦除的元素的下一个,循环体继续执行后,it会自动+1。
一个数学表达式在计算时,结果返回为最精确的类型(如int*float,结果为float)。
正确代码如下:
#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<iterator>
#include<algorithm>
#include<cstring>
using namespace std;
int gettick(int h,int m,int s)
{
return h*60*60+m*60+s;
}
const int window_starttime = gettick(8,0,0);
const int window_endtime = gettick(17,0,0);
struct Customer
{
int cometime; //来到时间
int protime; //处理时间,秒
};
int getfreewindow(int* windows,int k)
{
int mintime = windows[0],mink = 0;
for(int i=1;i<k;++i)
{
if(mintime > windows[i])
{
mink = i;
mintime = windows[i];
}
}
//注释1:该种情况就是,这个人是17点之前来的,但是前面有人结束后就已经是17点以后了,这种情况也不需要过滤,还是计算在内的。
//if(mintime>window_endtime) return -1;
return mink;
}
int cmp(const Customer& c1,const Customer& c2)
{
return c1.cometime < c2.cometime;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("test.txt","r",stdin);
#endif
int n,k;
scanf("%d%d",&n,&k);
vector<Customer> vcus;
for(int i=0;i<n;++i)
{
int h,m,s,p;
scanf("%d:%d:%d%d",&h,&m,&s,&p);
Customer cus;
cus.cometime = gettick(h,m,s);
cus.protime = min(60*p,60*60);
if(cus.cometime <= window_endtime) //过滤17点以后来的人
vcus.push_back(cus);
}
n = vcus.size();
sort(vcus.begin(),vcus.end(),cmp);
int twaittime = 0/*总等待时间*/,cnt=0/*得到处理的人数*/,windowstime[k]/*该窗口空闲时间*/;
for(int i=0;i<k;++i)
windowstime[i] = window_starttime;
for(int i=0;i<n;++i)
{
int iw = getfreewindow(windowstime,k);
if(iw==-1) break;
++cnt;
Customer &cus = vcus[i];
if(cus.cometime<windowstime[iw])
{
twaittime+= (windowstime[iw]-cus.cometime);
windowstime[iw] += cus.protime;
}
else
{
windowstime[iw] = cus.cometime + cus.protime;
}
}
if(cnt==0) printf("0.0\n");
else printf("%.1lf\n",1.0f*twaittime/cnt/60);
return 0;
}