【最短路】Aircraft
版权声明:本篇随笔版权归作者Etta(http://www.cnblogs.com/Etta/)所有,转载请保留原地址!
华夏60 超音速战斗机是当今世界上机动性能最先进的战斗机。战斗过程中的一个关键问题是如何在最短的时间内使飞机从当前的飞行高度和速度爬升/俯冲到指定的高度并达到指定速度,以便占据有利的战斗位置。
现假定只允许华夏60 执行以下三种基本飞行动作,并且只能在完成了一个基本动作的情况下再去执行另一个基本飞行动作。这样华夏60 的飞行可以表示成由这三种基本飞行动作组成的动作序列。
维持原速做恒速爬升飞行,直至飞行高度提高 ∆h 英尺;
水平加速飞直至速度提高1 马赫(1 马赫 ≈ 1200 公里/小时);
垂直俯冲飞行 ∆h 英尺,飞行速度会提高1 马赫。
同时假定飞机的初始飞行速度和执行每个基本飞行动作初始时刻的飞行速度都是1 马赫的整数倍,且不超过6 马赫;初始飞行高度和执行每个基本飞行动作初始时刻的飞行高度都为 ∆h 英尺( ∆h 是整数)的整数倍。
实验研究表明:在不同高度H 和不同的初始速度V 完成上述的三种基本飞行动作所需的时间也是各不相同的。表1~表3 给出了∆h = 15000英尺和最大飞行高度Hm = 75000英尺时完成这三种基本飞行动作所需的时间。
表1 恒速爬升飞行
V H |
1 |
2 |
3 |
4 |
5 |
6 |
0 |
12 |
12 |
12 |
11 |
12 |
14 |
15000 |
11 |
10 |
8 |
9 |
10 |
11 |
30000 |
9 |
8 |
6 |
7 |
8 |
8 |
45000 |
8 |
7 |
6 |
6 |
6 |
5 |
60000 |
8 |
6 |
6 |
6 |
6 |
5 |
表2 水平加速飞行
V H |
1 |
2 |
3 |
4 |
5 |
0 |
11 |
11 |
11 |
13 |
15 |
15000 |
10 |
10 |
9 |
9 |
10 |
30000 |
10 |
9 |
9 |
10 |
10 |
45000 |
9 |
8 |
9 |
9 |
10 |
60000 |
7 |
8 |
8 |
9 |
9 |
75000 |
7 |
7 |
7 |
8 |
8 |
表3 垂直俯冲飞行
V H |
1 |
2 |
3 |
4 |
5 |
30000 |
5 |
4 |
3 |
3 |
2 |
45000 |
4 |
3 |
3 |
2 |
2 |
60000 |
3 |
3 |
2 |
2 |
2 |
75000 |
3 |
3 |
2 |
2 |
2 |
根据表1~表3 的数据,欲使华夏60 战斗机从H = 0 英尺、V = 1 马赫的飞行状态达到H = 75000 英尺、V = 6马赫的飞行状态的最短飞行时间是79 秒,相应的飞行动作序列是:
恒速爬升飞行至15000 = H 英尺, 1 = V 马赫状态;
连续做两次水平加速飞行至H = 15000 英尺, V = 3 马赫状态;
连续做四次恒速爬升飞行至H = 75000 英尺, V = 3 马赫状态;
水平加速飞行至 H = 75000 英尺, V = 4 马赫状态;
连续做两次垂直俯冲飞行至H = 45000 英尺, V = 6 马赫状态;
连续做两次恒速爬升飞行至H = 75000 英尺, V = 6 马赫状态。
现在小明驾驶华夏60 战斗机以V1 马赫的速度飞行于H1 英尺高度,中队长发出了让他以V2 马赫的速度飞行于H2 英尺高度的指令。请你编写程序帮小明决策一下如何飞行才能花费最少的时间执行完中队长下达的命令。
输入:文件由四部分组成。
第一部分由一行构成,存放格式为:H1 V1 H2 V2 ∆h Hm 。
第二部分存放了表1 的内容,共有 Hm /∆h 行,每行有6 列。表中第i 行、第j 列的数据表示华夏60 战斗机在 ∆h*(i-1) 英尺的高度以j马赫的速度做恒速爬升飞行,飞行高度提高∆h英尺所需的时间。
第三部分存放了表2 的内容,共有 Hm /∆h+1 行,每行有5 列。表中第i 行、第j 列的数据表示华夏60 战斗机在 ∆h*(i-1) 英尺的高度以j 马赫的初始速度做水平加速飞行,飞行速度提高1 马赫所需要的时间。
第四部分存放了表3 的内容,共有 Hm /∆h-1 行,每行有5 列。表中第i 行、第j 列的数据表示华夏60 战斗机在 ∆h*(i+1) 英尺的高度以j 的初始速度做垂直俯冲飞行,飞行高度降低∆h英尺所需的时间。
注意:输入数据中所有的数据都是整数。
输出:
输出信息用两行来存放。第一行存放你求出的最优方案所需的时间。第二行存放该最优方案的动作序列(以R 表示恒速爬升飞行,A 表示水平加速飞行,D 表示垂直俯冲飞行)。第二行中不允许出现多余的字符(包括空白字符)。
输入
0 1 75000 6 15000 75000
12 12 12 11 12 14
11 10 8 9 10 11
9 8 6 7 8 8
8 7 6 6 6 5
8 6 6 6 6 5
11 11 11 13 15
10 10 9 9 10
10 9 9 10 10
9 8 9 9 10
7 8 8 9 9
7 7 7 8 8
5 4 3 3 2
4 3 3 2 2
3 3 2 2 2
3 3 2 2 2
输出
79
RAARRRRADDRR
一、分析问题
读完题用了很长的时间,但把它和图论联系起来想到建图的方法就不难。问题本质就是一个最短路,可以把每一个V与H的状态抽象为一个坐标点,用一维数组简化二维坐标加上队列SPFA 就水过去了O__O
二、解决问题
SPFA
三、代码实现
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 6 const int MA=2010,inf=4e8; 7 8 int h1,v1,h2,v2,st,en,dh,hm,n,m,t; 9 int sum,k; 10 int head[MA],dis[MA],ex[MA],pre[MA],w[MA]; 11 struct edge{ 12 int t,l,n,u; 13 }e[MA]; 14 queue<int>q; 15 char ch[]={' ','R','A','D'}; 16 17 int calc(int a,int b) 18 { 19 return m*a+b; 20 } 21 22 void build(int from,int to,int len,int u) 23 { 24 e[++sum].t=to; 25 e[sum].u=u; 26 e[sum].l=len; 27 e[sum].n=head[from]; 28 head[from]=sum; 29 } 30 31 void init() 32 { 33 scanf("%d%d%d%d%d%d",&h1,&v1,&h2,&v2,&dh,&hm); 34 n=hm/dh; 35 m=6; 36 h1/=dh;st=calc(h1,v1); 37 h2/=dh;en=calc(h2,v2); 38 39 for(int i=0;i<=n-1;++i)//恒速爬升 40 for(int j=1;j<=6;++j) 41 { 42 scanf("%d",&t); 43 int e=calc(i,j),f=calc(i+1,j); 44 build(e,f,t,1); 45 } 46 47 for(int i=0;i<=n;++i)//水平加速 48 for(int j=1;j<=5;++j) 49 { 50 scanf("%d",&t); 51 int e=calc(i,j),f=calc(i,j+1); 52 build(e,f,t,2); 53 } 54 55 for(int i=2;i<=n;++i)//垂直俯冲 56 for(int j=1;j<=5;++j) 57 { 58 scanf("%d",&t); 59 int e=calc(i,j),f=calc(i-1,j+1); 60 build(e,f,t,3); 61 } 62 } 63 64 void SPFA() 65 { 66 for(int i=0;i<=(n+1)*m;++i)dis[i]=inf; 67 dis[st]=0; 68 q.push(st); 69 while(!q.empty()) 70 { 71 k=q.front(); 72 q.pop(); 73 ex[k]=0; 74 for(int i=head[k];i;i=e[i].n) 75 { 76 if(dis[e[i].t]>=dis[k]+e[i].l) 77 { 78 dis[e[i].t]=dis[k]+e[i].l; 79 w[e[i].t]=e[i].u; 80 pre[e[i].t]=k; 81 if(!ex[e[i].t]) 82 { 83 ex[e[i].t]=1; 84 q.push(e[i].t); 85 } 86 } 87 } 88 } 89 } 90 91 void print(int x) 92 { 93 if(pre[x])print(pre[x]); 94 if(w[x])printf("%c",ch[w[x]]); 95 } 96 97 int main() 98 { 99 init(); 100 SPFA(); 101 printf("%d\n",dis[en]); 102 print(en); 103 printf("\n"); 104 return 0; 105 }