CodeForces - 977D:序列(DFS)

原题链接
泰泰学长喜欢玩数字(不知道什么奇怪的癖好)。他在黑板上写下一个数字 x ,然后进行 n-1 次以下两种操作:

x 除以3 (必须能整除才能进行,即 x mod 3=0)
x 乘以2
每次操作完成后,泰泰学长在黑板上写上这个操作后的新数字,并让这个新数字作为新的 x 继续下一次操作。最后黑板上有 n 个数字。

由于泰泰学长是随机在黑板上的位置写数字的,所以他最后忘记了顺序。现在泰泰学长只知道所有的数字,你能帮助泰泰学长找出一种可能的序列吗?

保证答案一定存在。

Input
第一行是数字总数 n (2 ≤ n ≤ 100)。第二行包含 n 个数字a1,a2,…,an (1 ≤ ai ≤3×10^18),注意是不按顺序的。

Output
输出 n 个数字,按照泰泰学长写数字的顺序排列。

保证答案一定存在。

Examples
Input
6
4 8 6 3 12 9
Output
9 3 6 12 4 8
Input
4
42 28 84 126
Output
126 42 84 28
Input
2
1000000000000000000 3000000000000000000
Output
3000000000000000000 1000000000000000000
Note
第一个样例中的可能顺序为:[9, 3, 6, 12, 4, 8]。此时开始的 x=9

题目描述

将给出的一串数字经过题目描述的操作之后,得到新的顺序,并输出

思路:很明显是dfs,由于不知道第一个开头数字是多少,所以需要试探每个数字作为开头,如果搜索完成,那么这个序列就符合条件,代码里面使用了map代替我们通常记录数字是否出现的book,这也是一个巧妙的地方,能够优化算法,应为你需要在这些数字中去寻找符合条件的是够存在,map就可以直接找到

代码如下

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <map>

using namespace std;

typedef long long ll;
ll a[105],vis[105];
map<ll, int> m;
int flag,n;
void dfs(ll num, int step)
{
    if(step >= n-1)
    {
        flag = 1;
        for(int i = 0;i < n;i++)
            printf("%lld ",vis[i]);
        printf("\n");
        return;
    }
    //如果该数字符合操作1的条件,并且数组中还有剩余
    if(num%3 == 0 && m.count(num/3))
    {
        m[num/3]--;
        vis[step+1] = num/3;
        dfs(num/3, step+1);
        m[num/3]++;
    }
    //数组中还有剩余
    if(m.count(num*2))
    {
        m[num*2]--;
        vis[step+1] = num*2;
        dfs(num*2, step+1);
        m[num*2]++;
    }
}

int main()
{
    int i;
    scanf("%d",&n);
    for(i = 0;i < n;i++)
    {
        scanf("%lld",&a[i]);
        if(m.count(a[i]))
            m[a[i]]++;
        else
            m[a[i]] = 0;
    }
    //从数组的每个数字进行试探
    for(i = 0;i < n;i++)
    {
        vis[0] = a[i];
        dfs(a[i],0);
        if(flag)
            break;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43327091/article/details/87901595
今日推荐