飞机调度(Now or later,LA 3211)
2016-02-21 20:57
435 查看
AC通道(Uva 1146):
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3587
每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种。
第 i 架飞机的早着陆时间为 Ei,晚着陆时间为 Li,不得在其他时间着陆。
你的任务是为这些飞机安排着陆方式,使得相邻两个着陆时间间隔的最小值(称为安全间隔)应尽量大。
每组数据第一行为飞机的数目 n(2≤n≤2000)。
以下 n 行每行两个整数,及早着陆时间和晚着陆时间。
所有时间 t 满足 0≤t≤107。
输入结束标志为文件结束符(EOF)。
44 156
153 182
48 109
160 201
55 186
54 207
55 165
17 58
132 160
87 197
这样,我们就把问题转化为了判定性问题,即是否能使相邻两个着陆时间差不小于 P。
我们可以构一张图。
图中编号为 2k+b(0≤b≤1,1≤k≤n) 的节点的值若为 1 ,表示第 k 架飞机,选择第 b+1 种着陆方式;值若为 0,则表示表示第 k 架飞机,不选择第 b+1 种着陆方式。
即一个节点表示一个决策。
而对于有向边 x -> y,表示选择决策 x,就可以推出必须选择决策 y。
怎样才可以从一个决策推出另一个决策呢?
我们可以发现,若决策 x 的着陆时间与决策 y 的着陆时间的间隔小于 P,那么如果选择了决策 x,那么就一定不能选择决策 y,即必须要选择决策 y 所决定的飞机的另一种着陆方式。
这样,我们就可以把到目前为止没有被访问过的节点,值设为 1,然后 DFS。
若发现矛盾(即 DFS 过程中,发现某个节点所对应的飞机的另一种着陆方式的节点的值为 1),就将该节点(即前文提到的“到目前为止没有被访问过的节点”)所对应的飞机的另一种着陆方式的值设为 1,再 DFS。
若还有矛盾,就无解了。
温馨提示(辛酸史):
- RE:邻接表数组要开到 (2n)2;
- WA:按照我的二分习惯,应该是
- TL:注意每次判定,不用把邻接表全部 memset,只要把需要用到的设为 0 就可以了。
#include <cstdio>
#include <cstring>
using namespace std;
inline int Max(int x,int y){
return x>y?x:y;
}
inline int abs(int x){
return x>0?x:(-x);
}
inline bool ok(int x,int y,int z){
return abs(y-x)<z;
}
int n;
int lat[20010],now[20010];
int head[401001],nxt[41000100],data[41000010];
int ss[401001];
bool vis[401001];
int cnt,maxn=0;
inline void add(int x,int y){
data[cnt]=y;nxt[cnt]=head[x];head[x]=cnt++;
}
bool dfs(int now){
if(((now&1)&&(vis[now-1]))||(vis[now+1]&&(!(now&1))))return false;
if(vis[now])return true;
ss[++maxn]=now;
vis[now]=true;
for(int i=head[now];i;i=nxt[i]){if(!dfs(data[i]))return false;}
return true;
}
bool pan(int x){
for(int i=1;i<=n*2+10;i++)head[i]=vis[i]=ss[i]=0;
for(int i=1;i<=n*n*4+10;i++)nxt[i]=data[i]=0;
cnt=1;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
if(ok(now[i],lat[j],x)){add(2*i+1,2*j+1);add(2*j,2*i);}
if(ok(lat[i],lat[j],x)){add(2*i,2*j+1);add(2*j,2*i+1);}
if(ok(lat[i],now[j],x)){add(2*i,2*j);add(2*j+1,2*i+1);}
if(ok(now[i],now[j],x)){add(2*i+1,2*j);add(2*j+1,2*i);}
}
for(int i=2;i<=n*2+1;i+=2)if(!vis[i]&&!vis[i+1]){
maxn=0;
if(!dfs(i)){
for(int j=1;j<=maxn;j++)vis[ss[j]]=false;
maxn=0;
if(!dfs(i+1))return false;
}
}
return true;
}
int main(){
while(scanf(“%d”,&n)!=EOF){
int l=0,r=0,ans=0;
for(int i=1;i<=n;i++){
scanf(”%d%d”,&now[i],&lat[i]);
r=Max(now[i],r);
r=Max(lat[i],r);
}
while(l<=r){
int mid=((long long)l+r)/2;
bool flag=pan(mid);
if(flag){
ans=Max(ans,mid);
if(l!=mid+1)l=mid+1;
else break;
}
else{
if(r!=mid-1)r=mid-1;
else break;
}
}
printf(”%d\n”,ans);
}
return 0;
}
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3587
飞机调度
Description
有 n 架飞机需要着陆。每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种。
第 i 架飞机的早着陆时间为 Ei,晚着陆时间为 Li,不得在其他时间着陆。
你的任务是为这些飞机安排着陆方式,使得相邻两个着陆时间间隔的最小值(称为安全间隔)应尽量大。
Input
输入包含若干组数据。每组数据第一行为飞机的数目 n(2≤n≤2000)。
以下 n 行每行两个整数,及早着陆时间和晚着陆时间。
所有时间 t 满足 0≤t≤107。
输入结束标志为文件结束符(EOF)。
Output
对于每组数据,输出安全间隔的最大值。Sample Input
1044 156
153 182
48 109
160 201
55 186
54 207
55 165
17 58
132 160
87 197
Sample Output
10Solution
首先,看到这个最小值最大,就毫不犹豫地想到了二分答案。这样,我们就把问题转化为了判定性问题,即是否能使相邻两个着陆时间差不小于 P。
我们可以构一张图。
图中编号为 2k+b(0≤b≤1,1≤k≤n) 的节点的值若为 1 ,表示第 k 架飞机,选择第 b+1 种着陆方式;值若为 0,则表示表示第 k 架飞机,不选择第 b+1 种着陆方式。
即一个节点表示一个决策。
而对于有向边 x -> y,表示选择决策 x,就可以推出必须选择决策 y。
怎样才可以从一个决策推出另一个决策呢?
我们可以发现,若决策 x 的着陆时间与决策 y 的着陆时间的间隔小于 P,那么如果选择了决策 x,那么就一定不能选择决策 y,即必须要选择决策 y 所决定的飞机的另一种着陆方式。
这样,我们就可以把到目前为止没有被访问过的节点,值设为 1,然后 DFS。
若发现矛盾(即 DFS 过程中,发现某个节点所对应的飞机的另一种着陆方式的节点的值为 1),就将该节点(即前文提到的“到目前为止没有被访问过的节点”)所对应的飞机的另一种着陆方式的值设为 1,再 DFS。
若还有矛盾,就无解了。
温馨提示(辛酸史):
- RE:邻接表数组要开到 (2n)2;
- WA:按照我的二分习惯,应该是
while(l<=r),但我写成了
while(l<r)……
- TL:注意每次判定,不用把邻接表全部 memset,只要把需要用到的设为 0 就可以了。
Code
[cpp] #include <iostream>#include <cstdio>
#include <cstring>
using namespace std;
inline int Max(int x,int y){
return x>y?x:y;
}
inline int abs(int x){
return x>0?x:(-x);
}
inline bool ok(int x,int y,int z){
return abs(y-x)<z;
}
int n;
int lat[20010],now[20010];
int head[401001],nxt[41000100],data[41000010];
int ss[401001];
bool vis[401001];
int cnt,maxn=0;
inline void add(int x,int y){
data[cnt]=y;nxt[cnt]=head[x];head[x]=cnt++;
}
bool dfs(int now){
if(((now&1)&&(vis[now-1]))||(vis[now+1]&&(!(now&1))))return false;
if(vis[now])return true;
ss[++maxn]=now;
vis[now]=true;
for(int i=head[now];i;i=nxt[i]){if(!dfs(data[i]))return false;}
return true;
}
bool pan(int x){
for(int i=1;i<=n*2+10;i++)head[i]=vis[i]=ss[i]=0;
for(int i=1;i<=n*n*4+10;i++)nxt[i]=data[i]=0;
cnt=1;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
if(ok(now[i],lat[j],x)){add(2*i+1,2*j+1);add(2*j,2*i);}
if(ok(lat[i],lat[j],x)){add(2*i,2*j+1);add(2*j,2*i+1);}
if(ok(lat[i],now[j],x)){add(2*i,2*j);add(2*j+1,2*i+1);}
if(ok(now[i],now[j],x)){add(2*i+1,2*j);add(2*j+1,2*i);}
}
for(int i=2;i<=n*2+1;i+=2)if(!vis[i]&&!vis[i+1]){
maxn=0;
if(!dfs(i)){
for(int j=1;j<=maxn;j++)vis[ss[j]]=false;
maxn=0;
if(!dfs(i+1))return false;
}
}
return true;
}
int main(){
while(scanf(“%d”,&n)!=EOF){
int l=0,r=0,ans=0;
for(int i=1;i<=n;i++){
scanf(”%d%d”,&now[i],&lat[i]);
r=Max(now[i],r);
r=Max(lat[i],r);
}
while(l<=r){
int mid=((long long)l+r)/2;
bool flag=pan(mid);
if(flag){
ans=Max(ans,mid);
if(l!=mid+1)l=mid+1;
else break;
}
else{
if(r!=mid-1)r=mid-1;
else break;
}
}
printf(”%d\n”,ans);
}
return 0;
}
相关文章推荐
- Win2003利用dfs(分布式文件系统)在负载均衡下的文件同步配置方案
- win2003分布式文件系统(dfs)配置方法[图文详解]
- win2003分布式文件系统及其部署 图文教程
- Hadoop2.6+jdk8的安装部署(1)——使用jar包安装部署【详细】
- Hadoop FS Shell
- DFS使用方法总结
- FastDFS注意事项
- 无忧技术带您预览DFS(分布式文件系统)管理控制台
- 快速排序里的学问:从猜数字开始
- C 语言实现迷宫 DFS算法
- 一幅图弄清DFT与DTFT,DFS的关系
- HDFS---Namenode
- HDFS ---- Services startup
- POJ1523 SPF dfs
- HDU 4898 The Revenge of the Princess’ Knight ( 2014 Multi-University Training Contest 4 )
- poj1731 Orders dfs
- Surrounded Regions
- Binary Tree Zigzag Level Order Traversal,Restore IP Addresses,Word Search,Simplify Path
- Search Insert Position,Search for a Range,Pow(x, n),Sqrt(x)
- Find Minimum in Rotated Sorted Array II