codeforces B. Fixed Points 解题报告

题目链接:http://codeforces.com/problemset/problem/347/B

题目意思:给出一个包含n个数的排列a,在排列a中最多只能作一次交换,使得ai = i 这样的匹配达到最多。

     作一次交换,最理想的情况是,在原来匹配好的序列中再匹配到两个数;最坏的情况是,即使作怎样的交换,都不可能再找到可以匹配的两个数,也就是说,根本不需要作交换。至于一般情况下,是可以再匹配到一个数的。

     我是设了两个数组(分别有n个数):a(用来存储待判断的序列a)和b(依次存储0~n-1个数)。然后判断a[i] 与b[i]是否相等,这是为了确定未作交换前两组序列本来能够匹配的数目;如果不符合就尝试交叉比较: a[i] = b[a[i]]  和 b[i] = a[b[a[i]]]  是否满足。若同时满足,代表做完一次交换可以达到最大的匹配,也就是匹配到2个。如果只满足其中一条,那么交换后可以达到一般的情况:匹配到一个数。否则,将会是最坏的情况,这时,干脆不要做交换。

     举个例子:假设 a 序列为:0 1 2 6 7 5 3 1

                          b 序列为:0 1 2 3 4 5 6 7

     第一次遇到的不匹配的数是 a[3], 由于考虑到b[i]存储数据的特殊性(依次存储0~n-1个数),因此通过  a[i] = b[a[i]] 的判断,a[3] = b[a[3]](b[6] = 6)和 b[3] = a[b[a[3]]] (a[b[6]] = a[6] = 3)   ,  发现两条式子都符合,那么可以达到最大的匹配。

     还有一个非常值得注意的细节,序列a存储的数有可能比n-1要大(假设n = 8,a[i]有可能是9(0 <= i <= n-1),所以要先判断。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 using namespace std;
 5 
 6 const int maxn = 100000 + 5;
 7 int a[maxn], b[maxn];
 8 
 9 int main()
10 {
11     int i, n, cnt, flag, flag1;   // flag用来标记达到最大的匹配数(2个),flag1标记一般情况交换后的匹配(1个)
12     while (scanf("%d", &n) != EOF)
13     {
14         for (i = 0; i < n; i++)
15         {
16             scanf("%d", &a[i]);
17             b[i] = i;
18         }
19         flag = flag1 = 0;
20         for (cnt = i = 0; i < n; i++)
21         {
22             if (a[i] == b[i])   // 统计未交换前的匹配数
23                 cnt++;    
24             else if (a[i] <= b[a[i]])   // a[i]有可能比n-1大
25             {
26                 if (b[i] == a[b[a[i]]] && a[i] == b[a[i]])
27                     flag = 1;  // 序列中至少存在一对通过交换后,在原来的基础上再匹配多2个数
28                 else 
29                     flag1 = 1; // 交换一次,可以在原来匹配的基础上匹配多1个数
30             }
31             
32         }
33         if (flag)
34             printf("%d\n", cnt+2);
35         else if (flag1)   // 注意不能跟flag一起做判断条件,条件语句写成flag && flag1是错误的,这样写应归纳到到一个if的判断里
36             printf("%d\n", cnt+1);
37         else 
38             printf("%d\n", cnt);    // 怎样交换都不能再找到匹配,干脆一次都不交换
39     }
40     return 0;
41 }
原文地址:https://www.cnblogs.com/windysai/p/3330993.html