海上逃亡

来源:互联网 发布:windows安装bugfree 编辑:程序博客网 时间:2024/04/28 15:46

海上逃亡

【问题描述】

你在海上逃亡!敌人随时都可能发现你!他们拥有着强大的雷达系统,和超远距离的导弹
系统。现在有一个好消息和一个坏消息:
好消息是:敌人的雷达系统是有范围限制的,因此只要你离开现在所在的位置尽量遥远,
就有希望能够逃脱。而坏消息是:你现在拥有的唯一的一艘战舰是从敌人营地中偷出的,他们
为了安全考虑编码了船的指令系统,使得你只能执行一些预设置的行船命令各一次。
这些命令在一些特定的组合下能够到达敌人希望到达的任何地方;但是此时的你,只希望
能够从中组合出一个能够尽量远离此处的序列:
 right X:其中 X 是一个 1 到 719 的整数,这个命令使得船顺时针转动 X 度。
 left X:其中 X 是一个 1 到 719 的整数,这个命令使得船逆时针转动 X 度。
 forward X:其中 X 是一个整数(1 到 10 3 ),使得船向正前方前进 X 的距离。
 backward X:其中 X 是一个整数(1 到 10 3 ),使得船向正后方前进 X 的距离。
你可以以任意的顺序执行这一些命令,但是每一命令只能执行一次。
【输入格式】
输入文件名为 ship.in。
第一行一个整数 n,敌人预编码的命令数。
接下来 n 行,每行表示一个命令。
【输出格式】
输出文件名为 ship.out。
一个浮点数,能够逃离的最远的距离,四舍五入到 6 位小数。
【输入输出样例】

ship.in ship.out 3 141.421356 forward 100 backward 100 left 90

见选手目录下的 ship/ship.in 和 ship/ship.ans。
【数据规模与约定】
对于 30%的数据,1≤n≤10。
对于 100%的数据,1≤n≤50。

【问题简述】

给定一个长度为 N 的指令序列,其中包括前进、后退、转弯。找到一个排序,使得离开距离最远。所有指令需且只能执行一次。

【数据规模与约定】

对于 30%的数据,1≤n≤10。
对于 100%的数据,1≤n≤50。

【可能的算法】

对于 30%的数据,可以直接进行暴力搜索,枚举所有可能的排列方式,取得其中离开最远
的指令方案。时间复杂度 O(n!)
对于 100%的数据,我们可以注意到在最开始和最结束的地方进行转弯是没有影响的,意
味着我们可以只选择其中的一部分转弯指令。并且我们不会选择在前进一段距离之后转弯再前
进一段距离,或是后退一段距离后转弯再后退——因为这必然使得距离原点距离不优(注意到原点角度无关)。同理先前进或是先后退也是对称的。
问题可以直接简化为:前进所有能前进的距离,之后转一个可选的角度,然后后退所有能
后退的距离。对于选择角度的旋转,我们可以通过类似动态规划的方法转移出所有可能转动的
总角度,最多有 360 种,利用余弦定理计算出第三边长。(c 2 = a 2 + b 2 - 2abcos(angle))
偷懒的做法:可以在这 360 种中枚举,选择一个最优解即可。
这便是这道题的满分算法。时间复杂度 O(n)。

代码

#include<cstdio>#include<algorithm>#include<cstring>#include<math.h>const int All = 360;int n;int forward[51], backward[51], left[51];int lenF, lenB, lenL;int front, back;bool angle[365], f[365];int main(void){    freopen("ship.in", "r",stdin);    freopen("ship.out", "w",stdout);    scanf("%d", &n);    for(int i = 1;i<=n;i++){        char str[10];        scanf("%s", str);        if(strcmp(str, "forward") == 0)            scanf("%d", &forward[++lenF]);        else if(strcmp(str, "backward") == 0)            scanf("%d", &backward[++lenB]);        else if(strcmp(str, "left") == 0)            scanf("%d", &left[++lenL]);        else if(strcmp(str, "right") == 0){            scanf("%d", &left[++lenL]);            left[lenL] = - left[lenL];        }    }    for(int i = 1;i<=lenF;i++)        front += forward[i];    for(int i = 1;i<=lenB;i++)        back += backward[i];    angle[0] = 1, f[0] = 1;    for(int i = 1;i<=lenL;i++){        for(int j = 0;j<360;j++)            if(angle[j])                f[(j+All+left[i]) % All] = 1;        for(int j = 0;j<360;j++)            angle[j] = f[j];    }    int maxAngle = 0;    for(int i = 0;i<=180;i++){        if(angle[180+i] || angle[180-i]){            maxAngle = i;            break;        }    }    double max = 0;    max = sqrt(pow(front + back*cos(M_PI*(double)maxAngle/180), 2) + pow(back*sin(M_PI*(double)maxAngle/180), 2));    printf("%.6llf", max);    return 0;}... prompt'''
0 0
原创粉丝点击