NOIP2012模拟试题【圆圈舞蹈( circle)

 

2.圆圈舞蹈( circle)

【问题描述】

     熊大妈的奶牛在时针的带领下,围成了一个圆圈跳舞。由于没有严格的教育,奶牛们之间的间隔不一致。

      奶牛想知道两只最远的奶牛到底隔了多远。奶牛A到B的距离为A顺时针走和逆时针走,到达B的较短路程。告诉你相邻两个奶牛间的距离,请你告诉奶牛两只最远的奶牛

到底隔了多远。

【输入】

     第一行一个整数N,表示有N只奶牛。(2≤N≤100000)

     接下来2~N+1行,第I行有一个数,表示第I-1头奶牛顺时针到第I头奶牛的距离。(1≤距离≤maxlongint,距离和≤maxlongint)

      第N+l行的数表示第N头奶牛顺时针到第1头奶牛的距离。

【输出】

     一行,表示最大距离。

【样例】

Circle.in

5

1

2

3

4

5

Circle.out

7

【样例解析】

      Circle.out所有奶牛I到J之间的距离和到达方式(顺为顺时针,逆为逆时针)如下:

 I\J

1

2

3

4

5

1

O

1 (顺)

3(顺)

6(顺)

5(逆)

2

1(逆)

O

2(顺)

5(顺)

6(逆)

3

3(逆)

2(逆)

0

3(顺)

7(顺)

4

6(逆)

5(逆)

3(逆)

0

4(顺)

5

5(顺)

6(顺)

7(逆)

4(逆)

0

所以,最远的两头奶牛为3到5,距离是7。

 

 分析样例(手写样例)时我们发现,最远距离总是接近圆圈周长的一半,对此我们可以证明

 因为奶牛A到B的距离为A顺时针走(dis)和逆时针走(ddis),到达B的较短路程,逆时针走(ddis)等于圆圈周长(sum)减去顺时针走的路程(dis),所以最远距离即求  min(sum-dis,dis) 的最大值

什么时候最大?

显然,当dis最接近sum/2时。

因此我们只需要求得每个点的最远距离即可解答=v=

 

下面是寻找每个点的最远距离的过程

(蓝字表示dis)

首先是1号点(o゜▽゜)o☆

当到达4号点时,dis=6;当到达5号点时,dis=10;

因此又引出一个细节:因为我们寻找的总是折中的点,所以要比较它和它相邻的点分别到起点的距离;

距离1号点最远的是4号点

当寻找起点为2号点的最远距离时,简单的方法是将起点顺时针移动,如果距离未达到sum/2,就将终点也顺时针移动

寻找完后,dis=6-1+4=9,距离是6,与1号点的最远距离比较,最远距离不变依然为6

重复上述步骤,最终最远距离为起点是3号点,终点是5号点的距离,即7

(っ*´Д`)っ下面放出代码

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<ctime>
 5 #include<algorithm>
 6 using namespace std;
 7 int n;
 8 long long sum;
 9 long long l[100001];
10 long long dis;
11 void work()
12 {
13     int u=0;
14     int v=0;
15     dis=0;
16     long long ans=0;
17     int j;
18     for(int i=1;i<=n;i++)//寻找距离一号点最远的点 
19     {
20         dis+=l[i-1];//***
21         if(dis>sum/2)
22         {
23             j=i;//记录这个点 
24             break;
25         }
26     }
27     ans=max(ans,min(sum-dis,dis));//因为我们寻找的是折中的点,所以需要比较两次,即它和它相邻的点; 
28     ans=max(ans,min(dis-l[j-1],sum-dis+l[j-1]));
29     for(int i=2;i<=n;i++)
30     {        
31         dis=dis-l[i-1];//寻找第i个点的最远距离,将起点从上一个点顺时针移动 
32         while(dis<sum/2)
33         {
34             dis+=l[j+1];
35             j++;//终点也顺时针移动    
36         }
37         ans=max(ans,min(sum-dis,dis));//与上面同理 
38         ans=max(ans,min(sum-dis+l[j-1],dis-l[j-1]));
39     }
40     printf("%lld ",ans);
41 }
42 void read()
43 {
44     scanf("%d",&n);
45     for(int i=1;i<=n;i++)
46     {
47         scanf("%lld",&l[i]);
48         sum+=l[i];//记录圆圈周长 
49     }
50 }
51 int main()
52 {
53     freopen("circle.in","r",stdin);
54     freopen("circle.out","w",stdout);
55     //clock_t start=clock();
56     read();
57     work();
58     //clock_t end=clock();
59     //printf("%d %d",start,end);
60     return 0;
61 }

 

 

转载于:https://www.cnblogs.com/orange-/p/4886914.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值