原题地址:
http://poj.org/problem?id=1083
题意:一条长廊的北边南边有编号从1到400的200个房间(分单双号),把一张桌子从房间m搬到房间n需要占用m、n之间的所有走廊(包括房间前的走廊),耗时为10分钟,给定所有需要搬动的(m,n)对,求尽可能同时移动桌子的情况下的最短耗时。
解题思路
刚开始读题以为是区间重叠的问题,画了很多线段想解法,最后觉得还是没有想到点子上(因为分类里说是水题- -),搜索了大神们写的思路,可以说是很巧妙了。
首先从图片中看到,相邻单-双号共享同一个走廊,因此如果为走廊指定数组下标,那么这个单双号对(x, x+1)共享一个下标x/2 or (x-1)/2,从1号到2号占用一次下标为0的走廊,从1号到4号占用一次下标为0和1的走廊,以此类推。
关键点是:能并发进行搬运的走廊一定不会重叠!如果第二组数据需要用到第一组的某个走廊,那这两组就不能同时搬运,即这个走廊必须分别占用两次。
综上,统计一下每个走廊会被占用的次数,最大占用次数即最大的并发数。
注:memset只能对字节操作,char占1个字节,因此用memset为char型数组赋予ASCII字符是没问题的,但是int占4个字节,如果memset(a, 1, sizeof(a))就会导致a的每个数字都变成0x01010101,因此,memset只能用于对int型数组清零。
AC代码如下
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int main()
{
int kase, corridor[201]; //corridor数组记录走廊的占用情况
cin >> kase;
while(kase--)
{
//数组清零,注意memset对字节操作,对int数组只能用于清零
memset(corridor, 0, sizeof(corridor));
int tables,m,n,i,j;
cin >> tables; //搬动桌子的数量
for (i = 0; i < tables; ++i)
{
cin >> m >> n;
if (m>n) swap(m,n); //保证m小于n
for (j = (m-1)>>1; j <= (n-1)>>1; ++j) //(m-1)/2~(n-1)/2的所有数组元素加1
++corridor[j];
}
int maxCnt = -1;
for (i = 0; i<200; ++i) //走廊的最大占用次数
maxCnt = (corridor[i]>maxCnt)?corridor[i]:maxCnt;
cout << maxCnt*10 << endl;
}
return 0;
}
内存占用: 728K 耗时:16ms
算法复杂度: O(n)