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