zoukankan      html  css  js  c++  java
  • LUOGU P1053 篝火晚会 (Noip 2015 )

    题目描述

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

    佳佳可向同学们下达命令,每一个命令的形式如下:

    (b1,b2,…bm−1,bm)(b_1, b_2,… b_{m-1}, b_m)(b1​,b2​,…bm−1​,bm​)

    这里 mmm 的值是由佳佳决定的,每次命令 mmm 的值都可以不同。这个命令的作用是移动编号是 b1,b2,…,bmb_1,b_2,…, b_mb1​,b2​,…,bm​ 的这m个同学的位置。要求 b1b_1b1​ 换到 b2b_2b2​ 的位置上, b2b_2b2​ 换到 b3b_3b3​ 的位置上,……,要求 bmb_mbm​ 换到 b1b_1b1​ 的位置上。执行每个命令都需要一些代价。我们假定如果一个命令要移动 mmm 个人的位置,那么这个命令的代价就是 mmm 。我们需要佳佳用最少的总代价实现同学们的意愿,你能帮助佳佳吗?
    输入输出格式
    输入格式:

    第一行是一个整数 n(3≤n≤50000)n(3 le n le 50000)n(3≤n≤50000) ,表示一共有 nnn 个同学。

    其后 nnn 行每行包括 222 个不同的正整数,以一个空格隔开,分别表示编号是 111 的同学最希望相邻的两个同学的编号,编号是 222 的同学最希望相邻的两个同学的编号,……,编号是 nnn 的同学最希望相邻的两个同学的编号。

    输出格式:

    一个整数,为最小的总代价。如果无论怎么调整都不能符合每个同学的愿望,则输出 −1-1−1 。

    输入输出样例
    输入样例#1:

    4
    3 4
    4 3
    1 2
    1 2

    输出样例#1:

    2

    说明

    对于30%的数据, n≤1000
    对于全部的数据, n≤50000

    2005提高组第三题

    解题思路

    首先此题有一个坑点是b是可以不连续的,也就是随便跳就行了。所以对于任意一个不匹配的点,可以让它到它的匹配点,它的匹配点在出来继续往后跳到它的匹配点的匹配点,以此类推就可以使数列匹配,最后的代价就是跳的次数,但这是O(n^2)的,考虑优化。因为它是一个环,所以就可以旋转这个操作,只需要记一个num数组,表示每个匹配点到原来点的距离的个数。然后取这个距离的个数的最大值mx,n-mx即为答案,因为我们可以将环旋转,使这mx个点达到匹配,剩余的点就为n-mx。注意还要反着跑一遍。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    const int MAXN = 50005;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int n,cnt,num[MAXN];
    int a[MAXN][3];
    int now[MAXN],ans=1e9;
    bool vis[MAXN];
    
    int main(){
        n=rd();
        for(register int i=1;i<=n;i++) a[i][1]=rd(),a[i][2]=rd();
        for(register int i=1;i<=n;i++)
            if((a[a[i][1]][1]!=i && a[a[i][1]][2]!=i )
            ||(a[a[i][2]][1]!=i && a[a[i][2]][2]!=i)){
                puts("-1");
                return 0;
            }
        int x=a[1][1];now[++cnt]=1;vis[1]=1;
        while(x!=1){
            if(vis[x]) break;
            now[++cnt]=x;
            vis[x]=1;
            if(!vis[a[x][1]]) x=a[x][1];
            else x=a[x][2];
        }
        for(register int i=1;i<=n;i++) num[(i-now[i]+n)%n]++;
        for(register int i=0;i<n;i++) ans=min(ans,n-num[i]),num[i]=0;
        cnt=0;now[++cnt]=1;memset(vis,false,sizeof(vis));x=a[1][2];vis[1]=1;
        while(x!=1){
            if(vis[x]) break;
            now[++cnt]=x;
            vis[x]=1;
            if(!vis[a[x][1]]) x=a[x][1];
            else x=a[x][2];
        }
        for(register int i=1;i<=n;i++) num[(i-now[i]+n)%n]++;
        for(register int i=0;i<n;i++) ans=min(ans,n-num[i]);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Android——ListView学习笔记(一)
    记录笔记——关于request.getRequestDispatcher().forward(request, response)的跳转问题
    Python + openCV 实现图像垂直投影和水平投影
    2020年-第三周助教总结-第二组
    Python记录——字符串的常用方法
    2020年-第二周助教总结-第二组
    Android开发——三种活动跳转方式
    2020年-第一周助教总结-第二组
    Python —— 实例化ndarray对象
    海信聚好看矫恒浩:构建异地双活混合云,利用公共云应对流量突增
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676934.html
Copyright © 2011-2022 走看看