zoukankan      html  css  js  c++  java
  • UVA10570-Meeting with Aliens(枚举)

    Problem UVA1616-Caravan Robbers

    Accept: 531  Submit: 2490
    Time Limit: 3000 mSec

    Problem Description

    Input

    Input will start with a positive integer, N (3 ≤ N ≤ 500) the number of aliens. In next few lines there will be N distinct integers from 1 to N indicating the current ordering of aliens. Input is terminated by a case where N = 0. This case should not be processed. There will be not more than 100 datasets.

     Output

    For each set of input print the minimum exchange operations required to fix the ordering of aliens.
     

     Sample Input

    4
    1 2 3 4
    4
    4 3 2 1
    4
    2 3 1 4
    0
     

    Sample Output

    0
    0
    1

    题解:这个题很有价值。想到倍长数列是比较自然的,但是接下来怎么办,如何快速求出将一个序列排成有序的最小交换次数,这里要用到一个结论:对于一个长度为n的元素互异的序列,通过交换实现有序的最小的交换次数是=n - n被分解成单循环的个数。具体证明见如下博客:

    https://blog.csdn.net/wangxugangzy05/article/details/42454111

    明白了这个,题目就变得很简单了,枚举起点,dfs找环,取最大值得出结果,这里要注意一点就是序列既可以是升序,也可以是降序,因此要倒着再枚举一遍,方法不变。

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int maxn = 500 + 10;
     6 
     7 int n;
     8 int num[maxn << 1];
     9 bool vis[maxn];
    10 
    11 void dfs(int st, int a) {
    12     if (vis[a]) return;
    13     vis[a] = true;
    14     dfs(st, num[st + a - 1]);
    15 }
    16 
    17 void dfs2(int st, int a) {
    18     if (vis[a]) return;
    19     vis[a] = true;
    20     dfs2(st, num[st - a + 1]);
    21 }
    22 
    23 int main()
    24 {
    25     //freopen("input.txt", "r", stdin);
    26     while (~scanf("%d", &n) && n) {
    27         for (int i = 0; i < n; i++) {
    28             scanf("%d", &num[i]);
    29             num[i + n] = num[i];
    30         }
    31 
    32         int Max = 0;
    33 
    34         for (int st = 0; st < n; st++) {
    35             memset(vis, false, sizeof(vis));
    36             int cnt = 0;
    37             for (int i = st; i < st + n; i++) {
    38                 if (!vis[num[i]]) {
    39                     dfs(st, num[i]);
    40                     cnt++;
    41                 }
    42             }
    43             Max = Max > cnt ? Max : cnt;
    44         }
    45 
    46         for (int st = 2 * n - 1; st >= n; st--) {
    47             memset(vis, false, sizeof(vis));
    48             int cnt = 0;
    49             for (int i = st; i >= st - n + 1; i--) {
    50                 if (!vis[num[i]]) {
    51                     dfs2(st, num[i]);
    52                     cnt++;
    53                 }
    54             }
    55             Max = Max > cnt ? Max : cnt;
    56         }
    57 
    58         printf("%d
    ", n - Max);
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    超棒的微软Metro风格Logo设计
    免费资源:Polaris UI套件 + Linecons图标集(AI, PDF, PNG, PSD, SVG)
    11套免费的wordpress模板主题
    SASS(Syntactically Awesome Stylesheets Sass)绝对新手入门教程
    分享网页加载速度优化的一些技巧?
    帮助开发者快速创建响应式布局的Boilerplate Responsive Boilerplate
    免费素材: Retina Glyph图标集 (包含100个AI & PNG格式的图标)
    响应式的前端框架 Groundwork
    帮助你搜索免费矢量,图标和PSD的搜索引擎 Freepik
    Toolbar.Js 帮助你创建提示风格的工具条jQuery插件
  • 原文地址:https://www.cnblogs.com/npugen/p/9709449.html
Copyright © 2011-2022 走看看