• 人以群分


    程序设计:人以群分

    思路:二分答案区间,难点在判断上,因为是要求最小值,所以为了得到最优解,我们要先将a数组排序,这样我们从中选择连续的一段一段作为一组这样得到的最小差值才是我们的最优解。我们思路上这样理解:我们从左往右进行分组,设pos=i表示[1~i]的人可以进行分组,开始先判断第一个区间,第一个区间左端点显然为1,枚举所有区间右端点的所有可能点(判断方程为a[m+i]-a[1]<=mid,右端点为m+i),对于每一种可能的点,我们继续往后判断是否可以进行分组,这时不在考虑它之前的状态考虑它后面一个点作为左区间,判断它可能的所有右区间,一直到判断区间时,左端点达到最右边。

    如果[1,i]的人可以进行分组,那么在对后面考虑时我们就不在考虑它,在对它后面[i+1,i+m+k]的区间进行考虑i+m+k为最后一个满足a[i+m+k]-a[i+1]<=mid的数,如果一个区间右边的数满足a[i+m+k]-a[i+1]<=mid,证明这个也可以进行分组,状态pos直接转移到i+m+k。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5e5+10;
    
    int vis[maxn];
    int a[maxn];
    int n,m;
    bool dfs(int pos,int mid)
    {
        if(vis[pos]==0)
            vis[pos]=1;
        else
            return false;
        if(pos==n)
            return true;
        for(int i=0; pos+m+i<=n&&a[pos+m+i]-a[pos+1]<=mid; i++)
        {
            if(dfs(pos+m+i,mid))
                return true;
        }
        return false;
    }
    
    int main()
    {
    
        cin>>n>>m;
        for(int i=1; i<=n; i++)
            cin>>a[i];
        sort(a+1,a+1+n);
        int l,r;
        l=0;
        r=1e9;
        while(l<r)
        {
            memset(vis,0,sizeof(vis));
            int mid=(l+r)/2;
    //        printf("mid=%d l=%d r=%d
    ",mid,l,r);
            if(dfs(0,mid))
                r=mid;
            else
                l=mid+1;
        }
        cout<<l;
    }
  • 相关阅读:
    数据流的小结
    二分法小结
    k倍区间
    【图文并茂】如何将英文版的Altium Designer Winter 09改成汉语版?
    【PCB操作】PCB拼板
    【图文并茂】如何将库文件移到另一个库
    PCB的收尾工作之补泪滴
    uCOS-II 学习笔记--------OSInit函数
    uCOS-II 学习笔记之任务管理--------任务就绪表和就绪组
    [leedcode 205] Isomorphic Strings
  • 原文地址:https://www.cnblogs.com/dongdong25800/p/10758534.html
Copyright © 2020-2023  润新知