[NOIP2005] 提高组 洛谷P1053 篝火晚会

题目描述

佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”。在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会。一共有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。

2005提高组第三题

在新的环中,如果a和b的相对位置没有变(即a相对于原位置左移了x个位置,b也相对于原位置左移了x个位置,向右同理),那么可以考虑:如果不移动两人,只移动其他人,最优解是多少?

显然,如果在移动时,相对移动了x位的人最多,那么这种情况下,等同于需要移动的人越少。

需要移动的人数=总人数-不需要移动的人数。 (题中佳佳要求别人交换的顺序可以任意指定,所以在可行的情况下,让m个人归位只需要m代价)

具体处理方法见代码

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 const int mxn=50010;
10 int read(){
11     int x=0,f=1;char ch=getchar();
12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
14     return x*f;
15 }
16 int w[mxn][2];
17 int c1[mxn],c2[mxn],r[mxn];
18 int vis[mxn];
19 int n;
20 int main(){
21     n=read();
22     int i,j;
23     for(i=1;i<=n;i++) w[i][0]=read(),w[i][1]=read();
24     r[1]=1;r[2]=w[1][0];
25     vis[r[1]]=vis[r[2]]=1;
26     for(i=2;i<n;i++){
27         if(r[i-1]==w[r[i]][0])r[i+1]=w[r[i]][1];
28         else if(r[i-1]==w[r[i]][1])r[i+1]=w[r[i]][0];
29             else{printf("-1
");return 0;}
30         vis[r[i+1]]=1;
31     }
32     for(i=1;i<=n;i++)if(!vis[i]){
33         printf("-1
");
34         return 0;
35     }
36     for(i=1;i<=n;i++){
37         c1[(r[i]-i+n)%n]++;//正序 
38         c2[(r[n-i+1]-i+n)%n]++;//逆序 
39         //WA 1: n-i+1写在了c2的外面 
40     }
41     int ans=0;
42     for(i=1;i<=n;i++){
43         ans=max(ans,c1[i]);
44         ans=max(ans,c2[i]);
45     }
46     printf("%d
",n-ans);
47     return 0;
48 }
原文地址:https://www.cnblogs.com/SilverNebula/p/6004815.html