POJ1083 Moving Tables

本文详细解析了POJ1083 Moving Tables问题,介绍了一个高效算法来解决在有限走廊宽度下如何最优化地完成多个房间间桌子的移动问题。通过对走廊进行分割,并统计每段走廊被占用的次数,最终确定了最小搬桌时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

POJ1083 Moving Tables
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 35297 Accepted: 11774

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 file. 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 3 + N -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.

Sample Input

3 
4 
10 20 
30 40 
50 60 
70 80 
2 
1 3 
2 200 
3 
10 100 
20 80 
30 50 

Sample Output

10
20
30

Source

 
解题思路:
     酒店有400个房间,如下编号对称分布在一条走廊两侧
     1 3 5 ... 397 399
        这里是走廊
     2 4 6 ... 398 400
 
     现在要从房间s->t搬桌子,有N组房间需要搬桌子,每搬一次10分钟(不论两个房间相隔多远).
     对于某组房间,搬桌子期间 s->t 之间的走廊会被占用,
     而其他组房间若没有使用到占用的走廊,则可同时搬,否则要等待.
     特别地,相对的两间房,共用一段走廊, 即若房间3的走廊被占用了,等同于房间4的走廊被占用了.
 
     给定N组需要搬的桌子,求最小可以搬完的时间.
 
 
    解题思路:
     感觉这题有点类似于多线程的同步互斥场景问题.
 
     ① 由于相对的两间房共用同一段走廊,为了方便处理问题,可以把所有奇数房间转换成偶数房间,反之亦可.
        如 1->6 可等价转换成 2->6, 尔后只需要关注一侧的房间即可(共200间)
     ② 根据房间号对走廊进行分割,可分割成200段走廊. 在从房间s->t搬桌子期间,对所使用到的每段走廊计数+1
     ③ 所有桌子搬完后,统计每段走廊的计数值(计数值代表这段走廊总共需要被占用的次数),
        由于题目并不考虑搬动期间的移动过程因素(类比多线程的事务锁),
        因此最大的一个计数值*10分钟 就是所求的最小搬完时间(因为只要走廊被占着,就只能在下一次再搬,不能同时搬) 
#include <iostream>
using namespace std;
 
const static int ROOM_NUM = 400;    // 最大房号
const static int TIME_UNIT = 10;    // 时间单位
 
/* 
 * 把偶数房号转换成奇数房号
 *  even 偶数房号
 * return 奇数房号
 */
int toOdd(int even);
 
void solve(void);
 
int main(void) {
    int testCase = 0;
    cin >> testCase;
    for(int t = 0; t < testCase; t++) {
        solve();
    }
 
    //system("pause");
    return 0;
}
 
 
int toOdd(int even) {
    return (even % 2 == 0 ? even - 1 : even);
}
 
 
void solve(void) {
    int useCnt[ROOM_NUM] = { 0 };       // 每个房间前的走廊被使用的次数
    int maxUseCnt = 0;                  // 被使用最多的次数
 
    int moveCnt = 0;                    // 需要搬动的桌子组数
    cin >> moveCnt;
    int* fromRooms = new int[moveCnt];  // 起点房间集
    int* toRooms = new int[moveCnt];    // 终点房间集
    for(int i = 0; i < moveCnt; i++) {
        int from, to;
        cin >> from >> to;
 
        // 使房号小的在前面
        fromRooms[i] = (from <= to ? from : to);
        toRooms[i] = (from > to ? from : to);
 
        // 把房号全部转换成奇数
        fromRooms[i] = toOdd(fromRooms[i]); 
        toRooms[i] = toOdd(toRooms[i]);
 
        // 相关房间前占用的走廊被使用次数+1
        for(int roomId = fromRooms[i]; roomId <= toRooms[i]; roomId += 2) {
            useCnt[roomId]++;
            if(maxUseCnt < useCnt[roomId]) {
                maxUseCnt = useCnt[roomId]; // 登记最大的使用次数
            }
        }
    }
    delete[] fromRooms;
    delete[] toRooms;
 
    // 计算最小的使用时间
    maxUseCnt = (maxUseCnt <= 0 || maxUseCnt > moveCnt ? moveCnt : maxUseCnt);
    int minUsedTime = maxUseCnt * TIME_UNIT;
    cout << minUsedTime << endl;
} 

 

转载于:https://www.cnblogs.com/alan-blog-TsingHua/p/10640127.html

1. 用户与权限管理模块 角色管理: 学生:查看实验室信息、预约设备、提交耗材申请、参与安全考核 教师:管理课题组预约、审批学生耗材申请、查看本课题组使用记录 管理员:设备全生命周期管理、审核预约、耗材采购与分发、安全检查 用户操作: 登录认证:统一身份认证(对接学号 / 工号系统,模拟实现),支持密码重置 信息管理:学生 / 教师维护个人信息(联系方式、所属院系),管理员管理所有用户 权限控制:不同角色仅可见对应功能(如学生不可删除设备信息) 2. 实验室与设备管理模块 实验室信息管理: 基础信息:实验室编号、名称、位置、容纳人数、开放时间、负责人 功能分类:按学科(计算机实验室 / 电子实验室 / 化学实验室)标记,关联可开展实验类型 状态展示:实时显示当前使用人数、设备运行状态(正常 / 故障) 设备管理: 设备档案:名称、型号、规格、购置日期、单价、生产厂家、存放位置、责任人 全生命周期管理: 入库登记:管理员录入新设备信息,生成唯一资产编号 维护记录:记录维修、校准、保养信息(时间、内容、执行人) 报废处理:登记报废原因、时间,更新设备状态为 "已报废" 设备查询:支持按名称、型号、状态多条件检索,显示设备当前可用情况 3. 预约与使用模块 预约管理: 预约规则:学生可预约未来 7 天内的设备 / 实验室,单次最长 4 小时(可设置) 预约流程:选择实验室→选择设备→选择时间段→提交申请(需填写实验目的) 审核机制:普通实验自动通过,高危实验(如化学实验)需教师审核 使用记录: 签到 / 签退:到达实验室后扫码签到,离开时签退,系统自动记录实际使用时长 使用登记:填写实验内容、设备运行情况(正常 / 异常),异常情况需详细描述 违规管理:迟到 15 分钟自动取消预约,多次违规限制预约权限 4. 耗材与安全管理模块 耗材管理: 耗材档案:名称、规格、数量、存放位置、
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值