POJ 1083 Moving Tables(区间+计数)

原题地址:

http://poj.org/problem?id=1083

题意:一条长廊的北边南边有编号从1到400的200个房间(分单双号),把一张桌子从房间m搬到房间n需要占用m、n之间的所有走廊(包括房间前的走廊),耗时为10分钟,给定所有需要搬动的(m,n)对,求尽可能同时移动桌子的情况下的最短耗时。
1083走廊图

解题思路

刚开始读题以为是区间重叠的问题,画了很多线段想解法,最后觉得还是没有想到点子上(因为分类里说是水题- -),搜索了大神们写的思路,可以说是很巧妙了。

首先从图片中看到,相邻单-双号共享同一个走廊,因此如果为走廊指定数组下标,那么这个单双号对(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)

posted @ 2017-03-29 10:21  Lecholin  阅读(155)  评论(0编辑  收藏  举报