Lucky Sorting(CodeForces-109D)[思维]

题意:给出一组数,要求从小到大排序,并且排序的过程中,发生交换的两个数至少一个为幸运数(十进制位均为4或7),问能否在(2×n)次交换内完成排序,如果能,输出交换的方案(不要求步骤数最少)。

思路:首先分为两种情况:

    1.所有的数均不为幸运数,则如果给出的序列已经排好序,答案为0,如果未排好序,则无法完成排序。

    2.存在幸运数,可得,只要存在幸运数,就一定能在2×n次以内完成排序。

      <1>具体的处理方法是将序列分为若干个闭环,闭环的意思可以举个例子来看,(xio表示下标为xi的元素排序后所在位置下标),如:x1->x2->x3->x1,这就是一个闭环,表示x1o==x2,x2o=x3,x3o=x1;

      <2>首先,一组数在上述规则下一定能分为若干闭环。

      <3>分完闭环后,正式进行交换,并且,确定一个幸运数作为操作数(需要且只需要一个),记录其所在闭环

        3.1首先,将操作数所在闭环进行排序(只需相邻之间两两交换即可,具体可参照上文对于闭环的定义)。

        3.2再借助操作数对剩余闭环依次排序。第一步为将操作数与待排序闭环中的任意元素交换,再用3.1中的方法操作,最后将操作数归位即可。

        3.3很容易证明,上述交换操作的总复杂度一定小于2×n.

代码如下:

  

#include <cstdio>
#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
typedef pair<int, int> P;
int n, arr[100010], inde[100010];
bool judge(int x)
{
    while (x != 0)
    {
        if (x % 10 != 4 && x % 10 != 7)
            return false;
        x /= 10;
    }
    return true;
}

bool cmp(int a, int b)
{
    return arr[a] < arr[b];
}
int main()
{
    int px = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        inde[i] = i;
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &arr[i]);
        if (!px && judge(arr[i]))
            px = i;
    }
    sort(inde + 1, inde + 1 + n, cmp);
    int iinde[100010];
    for (int i = 1; i <= n; i++)
    {
        iinde[inde[i]] = i;
    }
    if (!px)
    {
        int tans = 0;
        for (int i = 1; i <= n; i++)
            if (inde[i] != i)
            {
                tans = -1;
                break;
            }
        printf("%d", tans);
    }
    else
    {
        vector<P> ans;
        int book[100010] = {0};
        vector<int> aha[100010];
        int numAha[100010] = {0}, rd = 0, fgp;
        for (int i = 1; i <= n; i++)
        {
            if (book[i])
                continue;
            rd++;
            int p = i;
            while (!book[p])
            {
                book[p] = 1;
                aha[rd].push_back(p);
                if (p == px)
                    fgp = rd;
                p = inde[p];
            }
        }
        //flagRound
        memset(book, 0, sizeof(book));
        if (aha[fgp].size() > 1)
        {
            int ic = px;
            while (!book[inde[ic]])
            {
                book[ic] = 1;
                ans.push_back(P(ic, inde[ic]));
                ic = inde[ic];
            }
        }
        //restRound
        for (int i = 1; i <= rd; i++)
        {
            if (i == fgp || aha[i].size() == 1)
                continue;
            int ic = aha[i][0];
            ans.push_back(P(iinde[px], ic));
            while (!book[inde[ic]])
            {
                book[ic] = 1;
                ans.push_back(P(ic, inde[ic]));
                ic = inde[ic];
            }
            ans.push_back(P(iinde[px], iinde[aha[i][0]]));
        }
        printf("%d\n", ans.size());
        for (int i = 0; i < ans.size(); i++)
        {
            printf("%d %d\n", ans[i].first, ans[i].second);
        }
    }
    return 0;
}
By xxmlala

猜你喜欢

转载自www.cnblogs.com/xxmlala-fff/p/11612497.html