篝火晚会

Posted Z-Y-Y-S

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了篝火晚会相关的知识,希望对你有一定的参考价值。

题目描述

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

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

(b1, b2,... bm -1, bm)

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1: 复制
4

3 4

4 3

1 2

1 2
输出样例#1: 复制
2

说明

对于30%的数据,n <= 1000;

对于全部的数据,n <= 50000。

仔细观察发现,所有可能的情况都是由其中一种情况进行环移或翻转得到的,

 

比如样例有一种情况为:1 4 2 3

 

其余情况为:

 

3 1 4 2

 

2 3 1 4

 

4 2 3 1

 

3 2 4 1

 

1 3 2 4

 

4 1 3 2

 

2 4 1 3

 

(观察一下)

 

代价也就是与开始不相等的数的个数

 

比如要排成1 4 2 3

 

原序列1 2 3 4

 

只有1不用移,4 2 3都不在目标序列上,因此代价为3

 

因为 比如遇到一个不应该放在原来的位置上,

 

则把它放到目标位置上,

 

但又把另一个元素挤了出来,

 

将挤出来的元素放到目标位置上,

 

又会有元素被挤出来,

 

继续进行相同的操作.……

 

直到所有元素(人)都安排好(心满意足)了。

 

再计算代价,就是上述结论。

 

但是,环移操作很费时,n^2,怎么办?

 

当然不能直接移,可以记f[i]为有f[i]个元素要进行i次环移操作才能移到自己的位置上

 

求f[i]的最大值就行了

 

再翻转做一次就行了

 

判断也很好判断

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int cnt,a[50001],n,l[50001],r[50001],ans1[50001],ans2[50001],ans;
 7 int main()
 8 {int i,j;
 9   cin>>n;
10   for (i=1;i<=n;i++)
11     scanf("%d%d",&l[i],&r[i]);
12   a[1]=1;
13   for (i=1;i<=n;i++)
14     if (r[l[i]]!=i&&l[l[i]]!=i||l[r[i]]!=i&&r[r[i]]!=i)
15       {
16     cout<<-1;
17     return 0;
18       }
19   a[2]=l[1];
20   for (i=2;i<n;i++)
21     {
22       if (r[a[i]]==a[i-1]) a[i+1]=l[a[i]];
23       else a[i+1]=r[a[i]];
24     }
25   for (i=1;i<=n;i++)
26     {
27       ans1[(a[i]-i+n)%n]++;
28       ans2[(a[i]+i-1)%n]++;
29     }
30   for (i=0;i<n;i++)
31     ans=max(ans,max(ans1[i],ans2[i]));
32   cout<<n-ans;
33 }

 

以上是关于篝火晚会的主要内容,如果未能解决你的问题,请参考以下文章

篝火晚会

NOIP2005 篝火晚会

P1053 篝火晚会

2019.12.30日志

虫虫帝国----世界观和剧情

首届杜氏旅游龙舞狂欢节震撼上演