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

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

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

    (b_1, b_2,... b_{m-1}, b_m)(b1?,b2?,...bm?1?,bm?)

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

    输入格式
    第一行是一个整数n(3 le n le 50000)n(3≤n≤50000),表示一共有nn个同学。

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

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

    输入输出样例
    输入 #1复制
    4
    3 4
    4 3
    1 2
    1 2
    输出 #1复制
    2
    说明/提示
    对于30%的数据,n le 1000n≤1000;
    对于全部的数据,n le 50000n≤50000。

    2005提高组第三题

    这个锅题目描述得背,描述里b1,b2,...bm实在是太规则了,使我以为操作必须得从1开始,并且要连续...

    然后就没那么难了,我们考虑,把环破成链,假设有k个数在当前链和目标链中的位置相同,那么就有n-k个不相同的,我们每次操作只对这n-k个数进行,我们最优可以做到每操作x个数,就一次性把这x个数全放到正确位置上,比如说:

    1 2 3 4 5 6 7 8 9 10 -> 1 8 2 7 5 3 6 4 10 9

    先通过(10,8,1)-> 8 2 3 4 5 6 7 10 9 1

    再通过(3,5,4,7) 就可以了。

    (注意是环:8 2 7 5 3 6 4 10 9 1和1 8 2 7 5 3 6 4 10 9是一样的,所以要进行正 反计算)

    这样就做到了每次只操作位置不对的,实现了最小化代价。

    所以,结论就是:把初始链变成目标链的最小代价为n-k。(k的意义同上)

    .主要求 k的值

    (这是洛谷上的题解,主要为了理解为答案什么是n-k)(一开始我也很蒙)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define N 10005
    int n,a[N],b[N],c[N],l[N],r[N];//l[N]表示N的左边同学,r[N]表示N的右边的同学,b,c数组用来存当前位置与正确位置的正,反的差值
    int ans=0;
    int main()
    {
    scanf("%d",&n);
    for(int i=1;i<=n;i++){ scanf("%d%d",&l[i],&r[i]);}
    a[1]=1;a[2]=r[1];//初始化
    for(int i=2;i<=n;i++)//进行求正确的顺序的数组
    {
    if(a[i-1]==l[a[i]]) a[i+1]=r[a[i]];
    else if(a[i-1]==r[a[i]]) a[i+1]=l[a[i]];
    else printf("-1"),exit(0); //如果不满足,就结束程序
    }
    if(a[1]!=a[n+1]) printf("-1"),exit(0);//不能构成一个环 ,结束程序
    for(int i=1;i<=n;i++) b[(n+a[i]-i)%n]++,c[(n+a[n-i+1]-i)%n]++;//读入
    for(int i=0;i<n;i++) ans=max(ans,max(b[i],c[i]));//计算正确位置的最大值
    cout<<n-ans;//输出
    return 0;
    }
    本弱鸡的
    思想来自:博客园
    five 20

    Try and fail,but don't fail to try; 失败是成功之母
  • 相关阅读:
    HTML语义化
    OKAY take it away `electron-builder`一直提示这个
    gitbash选中不了自己想要的选择
    vue挂载
    vue关闭eslint
    第二天-5大浏览器内核和浏览器的组成
    第一天-JavaScript简介与历史
    bootstrap模态框遇到做复制的功能失效
    对象的key【键】和分别获取数组的key【键】和值
    AngularJS教程
  • 原文地址:https://www.cnblogs.com/Youio-bolg/p/11338702.html
Copyright © 2011-2022 走看看