Moving Tables
Description
Problem Description
The famous ACM (Advanced Computer Maker) Company has rented a floor of a building whose shape is in the following figure.
The floor has 200 rooms each on the north side and south side along the corridor. Recently the Company made a plan to reform its system. The reform includes moving a lot of tables between rooms. Because the corridor is narrow and all the tables are big, only one table can pass through the corridor. Some plan is needed to make the moving efficient. The manager figured out the following plan: Moving a table from a room to another room can be done within 10 minutes. When moving a table from room i to room j, the part of the corridor between the front of room i and the front of room j is used. So, during each 10 minutes, several moving between two rooms not sharing the same part of the corridor will be done simultaneously. To make it clear the manager illustrated the possible cases and impossible cases of simultaneous moving.
For each room, at most one table will be either moved in or moved out. Now, the manager seeks out a method to minimize the time to move all the tables. Your job is to write a program to solve the manager’s problem.
Input
The input consists of T test cases. The number of test cases ) (T is given in the first line of the input. Each test case begins with a line containing an integer N , 1<=N<=200 , that represents the number of tables to move. Each of the following N lines contains two positive integers s and t, representing that a table is to move from room number s to room number t (each room number appears at most once in the N lines). From the N+3-rd line, the remaining test cases are listed in the same manner as above.
Output
The output should contain the minimum time in minutes to complete the moving, one per line.
Examples
Input
3
4
10 20
30 40
50 60
70 80
2
1 3
2 200
3
10 100
20 80
30 50
Output
10
20
30
描述:
一个公司有400个房间,奇数在走廊的一侧,偶数在走廊的一侧,其中奇数和偶数房间共享一个走廊。(1和2 共用 3和4 共用)
现在给出n对房间,从a房间移动桌子到b房间,其中占用了(a-b)之间的走廊。(3房间移动到5房间间时 3房间 5房间 4房间 6房间 都不可用)
移动一次桌子花费10min,求移动所有桌子后花费的总时间。
正确解法:
刚开始以为是活动分配问题,排序开始的房间和后面的房间,可是奇数房间和偶数房间共用,就很难。
看书发现一种很简单的解法,桶排序吧。
其中 (a+1)/2 就可以把奇数和偶数房间合并成一个,现在就有了1-100个房间。
每次把 (a+1)/2 到 (b+1)/2 中间的房间全部 +1
最后数其中一个房间用的次数最多的 就是答案。
1 #include "pch.h" 2 #include<iostream> 3 #include<cstdio> 4 #include<string> 5 #include<cstring> 6 #include<cmath> 7 using namespace std; 8 int main() 9 { 10 int t,n; 11 cin >> t; 12 int a[210]; 13 while (t--) { 14 int n; 15 long long maxx = 0; 16 cin >> n; 17 memset(a, 0, sizeof(a)); 18 for (int i = 1; i <= n; i++) 19 { 20 int b,c; 21 cin >>b>>c; 22 for (int j = (b + 1) / 2; j <= (c + 1) / 2; j++) 23 a[j]++; 24 } 25 for (int i = 1; i <= 100; i++) 26 if (a[i] > maxx) maxx = a[i]; 27 cout << maxx * 10 << endl; 28 } 29 return 0; 30 }
QAQ我是辣鸡,数据中给出的a b 房间 也可能 (a>b)
1 #include "pch.h" 2 #include<iostream> 3 #include<cstdio> 4 #include<string> 5 #include<cstring> 6 #include<cmath> 7 using namespace std; 8 int main() 9 { 10 int t, n; 11 cin >> t; 12 int a[210]; 13 while (t--) { 14 int n; 15 long long maxx = 0; 16 cin >> n; 17 memset(a, 0, sizeof(a)); 18 for (int i = 1; i <= n; i++) 19 { 20 int b, c; 21 cin >> b >> c; 22 if (b > c) 23 { 24 int ttt = b; 25 b = c; 26 c = ttt; 27 } 28 for (int j = (b + 1) / 2; j <= (c + 1) / 2; j++) 29 a[j]++; 30 } 31 for (int i = 1; i <= 200; i++) 32 if (a[i] > maxx) maxx = a[i]; 33 cout << maxx * 10 << endl; 34 } 35 return 0; 36 }
给了我一个很神奇的思路,把奇数和偶数房间合并成一个,就可以用任务分配问题。
等我努力开创出来。
1 #include "pch.h" 2 #include<iostream> 3 #include<cstdio> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 struct student 10 { 11 int start, end; 12 }a[210]; 13 int cmp(student x, student y) 14 { 15 return (x.end < y.end); 16 } 17 int main() 18 { 19 int t; 20 cin >> t; 21 int b[210] = {0}; 22 while (t--) { 23 int n,c,d; 24 cin >> n; 25 memset(a,0,sizeof(a)); 26 memset(b, 0, sizeof(b)); 27 for (int i = 1; i <= n; i++) 28 { 29 cin >> c >> d; 30 c = (c + 1) / 2; 31 d = (d + 1) / 2; 32 if (c> d) { 33 a[i].start = d; 34 a[i].end = c; 35 } 36 else { 37 a[i].start = c; 38 a[i].end = d; 39 } 40 b[a[i].start]++; 41 } 42 sort(a + 1, a + n + 1, cmp); 43 int kk = n,ans=0; 44 while (kk) 45 { 46 int tt = 0; 47 ans++; 48 for (int i = 1; i <= n; i++) 49 { 50 if (tt <= a[i].start &&b[a[i].start] > 0) 51 { 52 tt = a[i].end; 53 b[a[i].start]--; 54 kk--; 55 } 56 } 57 } 58 cout << ans << endl; 59 } 60 return 0; 61 }
这种尽可能找最多移动房间数目(也就是对应的最多的活动节目数量)就是根据活动结束的时间排序,因为这样才能为未安排活动留下尽可能多的时间,同样的道理,这题我选择按房间尾数小的数排序也是希望留下的走廊的路径长度更长使尽可能多的房间可以移动。
如果你说只给你一次移动的机会,要你找到移动尽可能多的房间,我这种按照尾数排序的方式跟活动安排的例子无异都是正确的,但是这题不一样,最终你是要将所有的需要移动的房间移完,对于活动安排这个例子,也就意味着你必须将活动节目表上的节目全部安排完,问你最少需要多少天,这是同样的概念。
我从另外一个角度想,如果按房间尾数排序的话,那么在第二次遍历的时候第一个找到的房间的起始号并不是最前的,这时不是最优的,你要从总体上来看,你以为每次找到尽可能多的房间,对一次的遍历从房间尾号排序确实达到了这样的目的,但你的整体目的不是这样的,因为你最终还是要把所有的房间找完,并不是说仅是找最多的一次,你还要顾及后面的让每一次都尽可能找得更多的房间。所以不管前几次怎样,你现在要找的这一次需要越靠前开始找。
so 你要从每个房间的前面开始排序,而不是结尾。
1 #include "pch.h" 2 #include<iostream> 3 #include<cstdio> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 struct student 10 { 11 int start, end; 12 }a[210]; 13 int cmp(student x, student y) 14 { 15 return (x.start < y.start ); 16 } 17 int main() 18 { 19 int t; 20 cin >> t; 21 bool b[210]; 22 while (t--) { 23 int n, c, d; 24 cin >> n; 25 memset(a, 0, sizeof(a)); 26 memset(b, false, sizeof(b)); 27 for (int i = 1; i <= n; i++) 28 { 29 cin >> c >> d; 30 c = (c + 1) / 2; 31 d = (d + 1) / 2; 32 if (c > d) { 33 a[i].start = d; 34 a[i].end = c; 35 } 36 else { 37 a[i].start = c; 38 a[i].end = d; 39 } 40 } 41 sort(a + 1, a + n + 1, cmp); 42 int kk = n, ans = 0; 43 while (kk) 44 { 45 int tt = 0; 46 ans++; 47 for (int i = 1; i <= n; i++) 48 { 49 if (tt < a[i].start && b[i]==false) 50 { 51 tt = a[i].end; 52 b[i] = true; 53 kk--; 54 } 55 } 56 } 57 cout << ans*10 << endl; 58 } 59 return 0; 60 }