(贪心)hdu 1050 Moving Tables

题目:
hdu1050

题意:
有一个房间分布:
在这里插入图片描述
需要把桌子从room x 移动到 room y,在移动期间内连着room x 到 room y 的走廊将被无法使用(即这个区间内不能移动另一个桌子),移动一次桌子要10分钟。
说明了同时移动的可能情况和不可能发生的情况:
在这里插入图片描述输出中应包含完成移动的最短时间(以分钟为单位)。

思路:
因为这个不是一个一维的问题,所以要把room x 到 room y 转化成 走廊 x‘ 到 走廊 y’,如下图所示:
在这里插入图片描述
要分两次走的情况:(room1 to room4) and (room3 to room 6)
在这里插入图片描述
走廊2发生冲突,所有要走两次。

贪心策略:把每张桌子按起点从小到大排序,起点相等则按终点从小到大排序,遍历数组,下一张桌子就是距离上一张桌子的终点最近的起点的桌子。

错误的贪心策略:把每张桌子按终点从小到大排序,终点相等则按起点从小到大排序,遍历数组,下一张桌子就是距离上一张桌子的终点最近的起点的桌子(这是活动安排的贪心策略)。

as:
31 47
22 123
70 142
80 90
79 142
128 198
176 181
130 184
79 152

如果按错误的贪心策略,排完序后:
31 47
80 90
22 123
70 142
79 142
79 152
176 181
130 184
128 198
在这里插入图片描述
需要6次
————————————————————
如果按正确的贪心策略,排完序后:
22 123
31 47
70 142
79 142
79 152
80 90
128 198
130 184
176 181
在这里插入图片描述
需要5次

另一种思路:暴力模拟
因为数据不大,所有可以把走廊 x‘ 到 走廊 y’ 的所有点加一,最后遍历数组取最大值就是最小的次数(这里就不给代码了)
ps:如果数据大的话可以用线段树 + lazy 来做。

贪心的代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 220; 
struct node{
    int s, e;
    bool ok;
    friend bool operator < (const node &a, const node &b){
        return (a.s == b.s) ? a.e < b.e : a.s < b.s;
    }
}room[MAXN]; 
int main(){
//    freopen("_in.txt", "r", stdin);
//    freopen("_out1.txt", "w", stdout);
    int t, n, final, ans, tot;
    bool frist;
    scanf("%d", &t);
    while (t--){
        scanf("%d", &n);
        for (int i = 0; i < n; i++){
            scanf("%d%d", &room[i].s, &room[i].e);
            room[i].s = (room[i].s + 1) >> 1;
            room[i].e = (room[i].e + 1) >> 1;
            if (room[i].s > room[i].e)
                swap(room[i].s, room[i].e);
            room[i].ok = false;
        }
        sort(room, room+n);
        tot = ans = 0;
        while (true){
            frist = true;
            for (int i = 0; i < n; i++)
                if (frist && !room[i].ok){
                    final = room[i].e;
                    room[i].ok = true;
                    frist = false;
                    tot++;
                }
                else if (!room[i].ok && room[i].s > final){
                    final = room[i].e;
                    room[i].ok = true;
                    tot++;
                }
            ans++;
            if (tot == n)
                break;
        }
        printf("%d\n", ans * 10);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值