• 士兵排队


    NOIP模拟题,很简单,但是用了一个有意思的思想所以决定写个题解

    原题:

    在Gridland国家,有N个处于不同位置的士兵。该国上的地方都用两个坐标(X,Y)来表示。士兵能进行一次移动,每个士兵都可向上、向下、向左、或向右移动一个单位长,这样他就能把自己的X或Y改变1或-1。
    士兵们想进入一个水平线,彼此靠近,这样他们的最后位置就是(X,Y)、(X+1,Y),…,(X+N,Y))。水平线上的士兵的最后顺序以及整数X和Y,都是任意的。
    现在目标是求如此配置士兵的最少移动数。
    两个或两个以上的士兵在同一时间不处于同一位置。

    1 <= N <=10000

    首先一个小学级定理:多个数向一个数靠拢,如果每个数移动相同距离的花费相同,则最优解是中位数

    y求中位数即可,x怎么办呐

    由于最后x的格式固定为公差为1的等差数列,所以可以给x排完序后把x[i]-i,然后就把x的问题转化为多个数向中位数靠拢,然后就可以解决辣

    想题要注重特殊性而不是一般性

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 using namespace std;
     8 int read(){int z=0,mark=1;  char ch=getchar();
     9     while(ch<'0'||ch>'9'){if(ch=='-')mark=-1;  ch=getchar();}
    10     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    11     return z*mark;
    12 }
    13 int n,x[11000],y[11000];
    14 int main(){//freopen("ddd.in","r",stdin);
    15     cin>>n;  int N=(n+1)>>1;
    16     for(int i=1;i<=n;++i)  x[i]=read(),y[i]=read();
    17     sort(y+1,y+n+1),sort(x+1,x+n+1);
    18     for(int i=1;i<=n;++i)  x[i]-=i;
    19     sort(x+1,x+n+1);
    20     int bowl=0;
    21     for(int i=1;i<=n;++i)  bowl+=abs(y[i]-y[N])+abs(x[i]-x[N]);
    22     cout<<bowl<<endl;
    23     return 0;
    24 }
    25 
    26 
    27     
    View Code
  • 相关阅读:
    Windows 7 X64平台编译LLVM+clang
    web前后端分离漏洞分析防御
    微信小程序中显示html富文本的方法
    微信小程序上拉加载下拉刷新
    微信小程序横向滚动
    微信小程序中的自定义组件 以及 相关的坑
    一款易用、高可定制的vue翻页组件 vo-pages
    vue调用高德地图:vue-amap
    Vue 前端md5加密
    js手机号码中间用星号代替。银行卡后四位之外改为星号
  • 原文地址:https://www.cnblogs.com/JSL2018/p/6405669.html
Copyright © 2020-2023  润新知