zoukankan      html  css  js  c++  java
  • 篝火晚会

    篝火晚会(fire)

    【问题描述】
    佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小
    教官”。在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会。一共有 n 个同学,
    编号从1到n。一开始,同学们按照 1,2,……,n 的顺序坐成一圈,而实际上每个人都有两
    个最希望相邻的同学。如何下命令调整同学的次序,形成新的一个圈,使之符合同学们的意
    愿,成为摆在佳佳面前的一大难题。
    佳佳可向同学们下达命令,每一个命令的形式如下:
    (b1, b2,... bm -1, bm)

    这里m的值是由佳佳决定的,每次命令m的值都可以不同。这个命令的作用是移动编号
    是b1, b2, …… bm -1, bm的这m个同学的位置。要求b1换到 b2的位置上, b2换到b3的位置上, ……,
    要求bm换到b1的位置上。
    执行每个命令都需要一些代价。我们假定如果一个命令要移动 m 个人的位置,那么这个
    命令的代价就是m。我们需要佳佳用最少的总代价实现同学们的意愿,你能帮助佳佳吗?

    【输入文件】

    输入文件fire.in 的第一行是一个整数n(3 <= n <= 50000),表示一共有n个同学。
    其后n行每行包括两个不同的正整数,以一个空格隔开,分别表示编号是1的同学最希望相
    邻的两个同学的编号,编号是 2的同学最希望相邻的两个同学的编号,……,编号是n 的同
    学最希望相邻的两个同学的编号。

    【输出文件】
    输出文件fire.out 包括一行,这一行只包含一个整数,为最小的总代价。如果无论怎
    么调整都不能符合每个同学的愿望,则输出-1。

    【样例输入】
    4
    3 4
    4 3
    1 2
    1 2

    【样例输出】
    2

    【数据规模】

    对于30%的数据,n <= 1000;
    对于全部的数据,n <= 50000。

    篝火晚会(fire)

      看到这个题,分析条件,m个同学的变换(不一定连续,也不一定升序)构成目标序列,该同学直接走到他需要的点上,然后顶掉现在位置上的人就好了,反正最后肯定成环就是了。

      那么,我们只需要找到最大的不需要变换的人数,就可以得到最少的需要变换的人数。

      思路1,先构建目标序列(两个),然后将这个序列进行n-1次平移,比较,找到max值

      时间复杂度O(n^2);

      对于这个题的数据范围(50000),显然不行。

      那么,我们可以观察到,当这个目标序列平移时,由于初始序列单增,我们做差发现,平移只是使目标序列与原数列对应的差+-1而已,也就是说,差相等永远相等。差为0代表不移动的话,总有一种移法使得所有差中出现次数最多的数都为0;

      也就是说,构建好数列,只需要比较一次就好了

    详解见下图

    依照这种方法,相当于求差的众数出现的次数(注意有两种序列),然后答案为n-max

    相信构建序列大家都会~~~不会我也不说了

    program ex02;
    var a,l,r,b,c:array[1..100000] of longint;
        d:array[-100000..100000] of longint;
        n,i,j,k,tot,max:longint;
        v:array[0..100000] of boolean;
    begin
      readln(n);
      for i:=1 to n do
        readln(l[i],r[i]);
      k:=1; tot:=1;
      while v[k]=false do
      begin
        a[tot]:=k;
        v[k]:=true;
        if v[l[k]] then k:=r[k] else k:=l[k];
        inc(tot);
      end;
      if tot<n then 
      begin
        writeln(-1);
        //for i:=1 to n do write(a[i],' ');
        halt;
      end;
      for i:=1 to n do 
      begin
       b[i]:=(a[i]-i+n) mod n;
       inc(d[b[i]]);
       if d[b[i]]>max then max:=d[b[i]];
      end;
      fillchar(d,sizeof(d),0);  
      for i:=n downto 2 do
      begin
       c[i]:=(a[i]-(n-i+2)+n) mod n;
       inc(d[c[i]]);
       if d[c[i]]>max then max:=d[c[i]];
      end;
      inc(d[0]); if d[0]>max then max:=d[0]; 
      writeln(n-max); 
      //writeln(max);  
    end.  
        
  • 相关阅读:
    iOS万能跳转界面的方法
    CocoaPods版本更新
    iOS--开发小技巧(持续更新)
    RunTime--手势应用场景(很方便)
    牛逼的标签效果(封装好)
    直播点赞动画
    UI基础--自定义UISwitch
    StatusBar 更改状态栏颜色(ios7)
    ios版本更新提示
    IOS 两个UIImage 合成一个Image
  • 原文地址:https://www.cnblogs.com/fengjunjie/p/6021646.html
Copyright © 2011-2022 走看看