• 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 }
  • 相关阅读:
    Jetson Nano更改软件源
    树莓派开机启动VNC
    树莓派VNC复制粘贴
    数学之美-泰勒公式
    C++顺序容器
    eigen的简单用法汇总
    C++并发-同步并发
    C++ string类
    C++并发-互斥元
    Nginx常用命令
  • 原文地址:https://www.cnblogs.com/windysai/p/3330993.html
Copyright © 2020-2023  润新知