京东2017实习生笔试编程题-终结者C

来源:互联网 发布:js div切换滑动门效果 编辑:程序博客网 时间:2024/05/17 15:35

注:题目和参考来自于赛码网。赛码网

终结者C

  • 题目描述
    收到情报,有批新造的机器人要运输到前线。小C将去破坏机器人的运输。小C将激光炮放置在公路的一旁,等运输车经过的时候发射(假设激光炮一定可以射穿车辆)。由于能源有限,激光炮只能发射两次。可以认为激光炮放在坐标轴的原点处,并向y轴正方向发射。每辆运输车可以看作是一个矩形,起始的x轴坐标为Xi ,所有的车均位于第一象限,长度为Li,速度为1,朝x轴负方向运动。即经过t时间后,该车车头的x坐标为Xi-t,车尾坐标为Xi-t+Li 。只要打中车的任何一个部分就算击中。
    请你算算,他在哪两个时刻发射,才能摧毁最多的运输车。
    如图

  • 输入
    第一行一个正整数 n ( 2≤N≤200 ),表示运输个的数量。
    接下来n行,每行两个整数X和L(1≤X、L≤109),表示一辆车的x轴坐标和长度。

  • 输出
    输出最多可以摧毁的运输车数量。
  • 样例输入
    4
    2 2
    3 1
    5 2
    7 3
  • 样例输出
    4
  • 时间限制
    C/C++语言:1000MS其它语言:3000MS
  • 内存限制
    C/C++语言:65536KB其它语言:589824KB

我的想法

首先,由于运输车的速度相同,所以他们的相对位置不变,要求在哪两个时刻发射,能摧毁最多的运输车,也就是哪两个时刻通过y轴的车的数量最多。但我们可以假定车不动,而是Y轴向右移动。
它这儿由于X、L较小,所以我觉得可以直接枚举所有的 两个时刻的组合,去求这些情况下,可以击中的运输车数。

代码如下:

//只枚举所有的位置作为激光炮的发射时刻 #include<iostream>using namespace std;#define maxn 201#define maxDistance 109int main(){    int n,length;    int a[maxn],b[maxn];    //a[],b[]分别对应车头、车尾的位置     int maxCars = 0;        //最多被击中的运输车数量     cin>>n;    for(int i=0; i<n; i++)    {        cin>>a[i];        cin>>length;        b[i] = a[i]+length;    }    //直接枚举两个发射时刻,并计数可以摧毁的车的数量    for(int i=0; i<maxDistance; i++)        //第一个发射时刻     {        for(int j=i+1; j<=maxDistance; j++) //第二个发射时刻         {            int count = 0;          //初始化有0个车             for(int k=0; k<n; k++)  //检查k个车哪些可以被击中             {                if( (i>=a[k]&&i<=b[k]) || (j>=a[k]&&j<=b[k]) )                {                    count++;                }            }             if(maxCars<count)   maxCars = count;        }    }    cout<<maxCars<<endl;        return 0;}

但是提交后显示部分通过,提示如下

所有测试数据正确率为69.9999988079071%!
可以尝试再次完善代码,并调试,争取全部AC通过
输入:
148
127067 4537
120783 18036
132226 15186
107038 9854
125629 11225
115748 19924
103359 32258
124766 4945
114955 23319
132726 25412
121025 20356
131001 22550
109496 18585
109515 17965
123342 8076
117913 16143
131196 21949
125072 20427
114606 26174
124429 32405
106705 20627
129812 19376
130093 16566
116036 14737
129141 30815
105994 8257
106652 23937
130838 20483
101355 21016
101131 18231
117841 14626
102011 32638
104186 19691
101650 5663
121634 10894
110353 21417
113452 14009
107262 22234
105454 16304
116634 26304
114256 149
111124 12318
104213 27110
124028 29201
121080 21319
116858 24051
124155 31362
115264 11904
103676 29644
126909 14903
103561 28490
124948 1283
113653 30675
102220 5403
106923 3832
119369 3879
120259 19009
122619 23972
130003 21946
109781 26505
112392 32686
125313 6699
105589 12723
105938 19038
106410 31462
106234 12509
109961 3960
106493 1516
125269 24938
128869 59
114700 13972
126264 15118
116215 24556
107815 18331
103039 30213
129288 28083
101954 16086
120710 24485
124774 8381
129815 25952
106541 18116
101679 17111
125898 23074
100788 23978
118132 29957
128689 26114
110008 12942
115790 1724
121363 29
125184 24779
107200 5072
101885 21975
101071 11334
122867 26154
114295 32169
120825 9677
115629 28651
102598 3310
104693 4687
130080 10117
112249 26668
101528 26680
107864 29422
108405 8827
106816 7517
127726 28667
129087 27682
119964 1341
105686 6022
111662 14722
106064 29310
120415 17903
129873 17125
123941 32746
131762 28424
127531 4807
112268 9319
105602 31908
124307 23482
101012 21137
126630 24115
126809 4085
123556 12291
121293 29997
129152 1055
125345 14709
100248 7492
113712 5132
130114 16440
107958 24723
129704 6996
101052 25270
107479 18239
126423 27919
110866 17660
132498 28487
121196 7463
126633 12159
112022 1147
118392 13038
103925 10648
129458 6603
130807 4099
127830 29293
114600 7279
120799 18353
120448 13883
100540 28316
您的输出:
0

这样显然和题目的要求:每行两个整数X和L(1≤X、L≤109) 有一些不同,不过如果是X,L的值可能很大,就需要程序进行优化。我参考了下面的提示:

注意到本题中所有运输车的相对位置不变,于是可以看成所有的运输车不动,但是我们可以在X轴上,选择两个位置,发射激光炮。这样问题就变成了,选出两个位置,使得摧毁的运输车最多。直接枚举位置的坐标,会使得枚举量太大。我们考虑如果在x处发射了一次激光炮,摧毁了运输车集合S。那么我们可不可以稍微移动一下这个发射激光炮的位置,使得也能摧毁S的运输车集合呢?先不妨考虑把激光炮向左移动,假设此时激光炮只要在向左移动任意小的距离,都会使得破坏的集合不为S,那么此时激光炮的坐标,必然是S中某个运输车的车头。同理,向后移动,遇到了某个车尾也就不能移动了。由此得出,我们可以只枚举激光炮放在某个车头或者某个车尾的坐标上,由此得出答案。定义集合X:
X = {Xi,Xi+Li | 1 < i < n};
依次枚举集合X中的两个元素x; y,我们判断把激光炮放在x和y两处的时候,能摧毁多少运输车,判断只要枚举一遍所有的运输车即可。问题总的复杂度为O(n3)。

我修正后的代码如下:

//只枚举所有的车头位置作为激光炮的发射时刻 #include<iostream>using namespace std;#define maxn 201int main(){    int n,length;    int a[maxn],b[maxn];    //a[],b[]分别对应车头、车尾的位置     int maxCars = 0;        //最多被击中的运输车数量     cin>>n;    for(int i=0; i<n; i++)    {        cin>>a[i];        cin>>length;        b[i] = a[i]+length;    }    //枚举两个车头位置a[i]和a[j]作为发射时刻,并计数可以摧毁的车的数量    for(int i=0; i<n; i++)           {        for(int j=i+1; j<n; j++)            {            int count = 0;          //初始化有0个车             for(int k=0; k<n; k++)  //检查k个车哪些可以被击中             {                //满足 a[i]>=a[k]&&a[i]<=b[k] 表示第k个车被a[i]时刻的激光炮打中                 if( (a[i]>=a[k]&&a[i]<=b[k]) || (a[j]>=a[k]&&a[j]<=b[k]) )                {                    count++;                }            }             if(maxCars<count)   maxCars = count;        }    }    cout<<maxCars<<endl;        return 0;}

如有不正确的地方,还望您能指出,多谢!

0 0
原创粉丝点击