SRM479

    回到学校后硬盘主板各种悲剧,终于有时间再来做TC了.

 

DIV1

250 TheCoffeeTimeDivOne

 

题意:飞机上有一排n个座位依次标号为1...n,空服需要为这n个乘客倒茶或咖啡,茶座或咖啡座在排头(位置0)。空服需要在茶座或咖啡座倒一壶茶或咖啡,然后走到乘客座位处倒茶或咖啡,一壶最多服务7人。现在告诉你:1,每个座位间走动花费1时间;2,装一壶需要47时间;3,在座位处为乘客倒茶或咖啡需要4时间。给定n和需要茶的乘客标号,问最少多少时间能够全部倒完。

 

每个乘客都要倒一次水,时间一定4*n;装一壶可以服务7个人,肯定尽量用满,所以也时间一定(n_tea+6)%7+(n_cof+6)%7;走动时间就是需要考虑的,装一壶就要走一来回,不难发现最远服务的那个就是来回的距离,所以从排尾开始服务。比赛时用的是O(n)时间+O(n)空间,但是因为返回值写成了int,掉挂了,赛后看大牛代码发现可以不用O(n)的空间。

long long TheCoffeeTimeDivOne::find(int n, vector <int> tea) { int i; long long res = 0; res += n*4; sort(tea.begin(), tea.end()); int pos_tea = tea.size()-1; int last = n; while(pos_tea>=0&&last==tea[pos_tea]) { last--; pos_tea--;} while(last>0) { res += last*2 + 47; int cnt = 7; while(cnt--) { last--; while(pos_tea>=0&&last==tea[pos_tea]) { last--; pos_tea--;} } } for(i = 0; i < tea.size(); i++) { if(i%7==0) { res += tea[tea.size()-i-1]*2 + 47; } } return res; }

 

500 TheAirTripDivOne

 

题意:有1到n共n个城市,在这些城市之间有一些单程航线。每个航线给出5个属性,A,B,F,T,P分别表示航线起点,航线终点,首次航班时间,起点到终点花费时间,两趟航班的时间差。现在要在time时间内从城市1到城市n,而且每到一个城市要等待一段时间后才能坐下一个航班,整个过程中最短的那段等待时间叫安全系数,求最长的安全系数。

 

开始看错题了,想用dp写,但是time太大了,于是又进了hhanger大牛的blog...二分安全系数+dijkstra验证,有三个地方需要注意。1,假定安全系数以后,每次出发时间就是在到达该地后时间加上安全系数后的第一趟航班的出发时间;2,最短路的时候,需要找到相同的子过程,如果保存到达每个城市的时间,那么在城市1的值就不需要包括安全系数了;3,数据范围超过了int。

 

struct edge_t { int a, b, next; long long f, t, p; }; int head[500]; edge_t edge[500]; int n, deadline; const long long inf = 2000000000; void MakeGraph(vector<string> flights) { string str = ""; for(int i = 0; i < flights.size(); i++) str += flights[i]; for(int i = 0; i < str.size(); i++) if(str[i]==',') str[i] = ' '; int ne = 0; memset(head, -1, sizeof(head)); stringstream ss(str); int a, b, f, t, p; while(ss >> a >> b >> f >> t >> p) { ne++; edge[ne].a = a, edge[ne].b = b, edge[ne].f = f, edge[ne].t = t, edge[ne].p = p; edge[ne].next = head[a]; head[a] = ne; } } long long GetNextTime(long long t, int f, int p) { if(t < f) return f; //可以坐最早航班 int mod = (t-f)%p; if(mod==0) return t; //等待后刚好能坐到航班 return (p-mod) + t; } bool IsValid(int safe) { long long dist[500]; char vstd[500]; int i, j; for(i = 1; i <= n; i++) dist[i] = inf, vstd[i] = 0; dist[1] = 0, vstd[1] = 1; for(j = head[1]; j != -1; j = edge[j].next) { int next = edge[j].b; long long stime = GetNextTime(dist[1], edge[j].f, edge[j].p); if(dist[next] > stime + edge[j].t) dist[next] = stime + edge[j].t; } for(i = 1; i < n; i++) { long long mind = inf; int now = -1; for(j = 1; j <= n; j++) { if(!vstd[j] && dist[j]<mind) mind = dist[j], now = j; } if(now==-1) break; vstd[now] = 1; for(j = head[now]; j != -1; j = edge[j].next) { int next = edge[j].b; long long stime = GetNextTime(safe+dist[now], edge[j].f, edge[j].p); if(dist[next] > stime + edge[j].t) dist[next] = stime + edge[j].t; } } if(dist[n] <= deadline && dist[n]!=inf) return true; return false; } int TheAirTripDivOne::find(int _n, vector <string> flights, int time) { n = _n; deadline = time; MakeGraph(flights); int ans = -1; int left = 1, right = time; while(left <= right) { int mid = (left+right)/2; if(IsValid(mid)) { ans = mid; left = mid+1; } else right = mid-1; } return ans; }

 

1000 TheBoardingDivOne

 

还没看懂题。。

 

 

DIV2

 

TheBoardingDivOne

 

250 TheAirTripDivTwo

 

大水题。

 

500 TheCoffeeTimeDivTwo

 

就是DIV1的250,n的数据范围从44777777改成了1000。

 

1000 TheBoardingDivTwo

 

同DIV1的1000

你可能感兴趣的:(SRM479)