题目:
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;
}