题目:
著名的ACM公司租了一层楼,楼层的布局如下:
该楼层共有400个房间,每边200个房间。最近,公司想进行一些调整,其中包括在房间之间移动很多桌子。因为楼道很窄,桌子很大,只有一张桌子能通过楼道,所以有必要指定一个计划来使桌子移动更加高效。将桌子从一个房间移动到另外一个房间可以在10分钟内完成,当桌子从房间i移动到房间j时,从房间i到房间j部分的楼道被占用(闭区间)。在10分钟内,移动多张桌子如果不共享楼道的话,可以同时进行。下面列举了一些同时移动桌子可能的情况和不可能的情况:
对于每一个房间,至多有一张桌子移出或移进,如何找到一种方法使得移动桌子的时间最短?
输入:
输入包含T个测试用例,第一行输入测试用例的个数T,接下来依次输入每个测试用例的数据。每个测试用例的第一行输入需要移动的桌子数N,1<=N<=200,接下来的N行输入两个整数s和t,表示桌子从房间s移动到房间t。每个房间在N行输入中至多出现一次。
输出:
输出每个测试用例移动完所有桌子需要的最少时间。
样例输入:
3
4
10 20
30 40
50 60
70 80
2
1 3
2 200
3
10 100
20 80
30 50
样例输出:
10
20
30
解题思路:
1 将表示区间的数字统一转换成奇数,如[2,4]变为[1,3]
2 如果区间开始数字比结束数字大,则反转区间,如[3,1]反转为[1,3]
3 将区间变为前闭后开区间,如[1,3]变为[1,5)
4 将表示区间的数字统一排序,区间开始数字类型为“S”,区间结束数字类型为“T”,排序时如果数字相同,则类型为“T"的排在前面。
5 设定统计变量count=0。顺序扫描排序后的数组,遇到类型为"S"的数字count++,遇到类型为"T"的数字count--,记录count达到的最大值max。
6 count的最大值max即为两两互斥区间的最大数目,所以最后输出的结果为max*10。
代码:
#include<stdio.h> struct Node { int num; char type; }; int partition(struct Node *list, int start, int end) { struct Node pivot,temp; int i,j; pivot = list[start]; i=start; j=i+1; while(j<=end) { if(list[j].num < pivot.num || (list[j].num==pivot.num && list[j].type=='T')) { i++; temp = list[j]; list[j] = list[i]; list[i] = temp; } j++; } temp = list[i]; list[i] = pivot; list[start]=temp; return i; } void quikSort(struct Node *list, int start, int end) { int index; if(start>=end) return; index = partition(list, start, end); quikSort(list, start, index-1); quikSort(list, index+1, end); } int main() { int cases,n,i,j,s,t,len,count,max,temp; struct Node list[400]; scanf("%d", &cases); //输入测试用例数目 for(i=0; i<cases; i++) { scanf("%d", &n); for(j=0; j<n; j++) { scanf("%d %d", &s, &t); //统一转换成奇数 if(s%2==0) s--; if(t%2==0) t--; if(s>t){temp=s; s=t; t=temp;} //转换成前闭后开区间 t+=2; //保存 list[j*2].num=s; list[j*2].type='S'; list[j*2+1].num=t; list[j*2+1].type='T'; } //排序 len = 2*n; quikSort(list, 0, len-1); //计算两两互斥区间的最大数目 max=count=0; for(j=0; j<len; j++) { if(list[j].type=='S') { count++; if(count > max) max=count; } else count--; } printf("%d\n", max*10); } return 0; }