2020牛客国庆集训派对day4 J-Jokewithpermutation(DFS)

地址:https://ac.nowcoder.com/acm/contest/7831/J

题意:

一串数字,包含1~n,用空格将它们分开,输出任意一种。

解析:

本来想着,顺序看,先输出<10的,然后是>=10的,对于0特判输出两位。

但是有个样例,不行:1011987654321。输出10,1,19,但是很明显,这个串的最大值才11。如果先对n=(len-9)/2+9呢,进行最大值的判断来判定是输出单个还是两位数?很麻烦,很难判定。

所以dfs进行暴力枚举,但并不是枚举1~n的全排列,而是对于1~n,每次判断其在串s的位置,标记掉,dfs(n-1)。n>=10找两位的,<10找一位的。如果每次都能找到,那么最后n==0,这个时候一定是符合条件的一组,输出即可。如果出现一组符合条件的组,就需要剪枝,终止其他的dfs。

#include <bits/stdc++.h>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
//vector<int>g[maxn];
int vis[110];
string s;
int len,n,ok=0;
void dfs(int x)
{
    if(ok)
        return ;
    if(x==0)
    {
        ok=1;
        cout<<s[0];
        for(int i=1;i<len;i++)
        {
            if(vis[i]==vis[i-1])
                cout<<s[i];  //>=10
            else
                cout<<" "<<s[i];
        }
        return ;
    }
    if(x>=10)
    {
        int a=x/10,b=x%10;
        for(int i=0;i<len;i++)
        {
            if(!vis[i]&&!vis[i+1]&&(s[i]-'0')==a&&(s[i+1]-'0')==b)
            {
                vis[i]=vis[i+1]=x;
                dfs(x-1);
                if(ok)
                    return ;
                vis[i]=vis[i+1]=0;
            }
        }
    }
    else
    {
        for(int i=0;i<len;i++)
        {
            if(!vis[i]&&(s[i]-'0')==x)
            {
                vis[i]=x;
                dfs(x-1);
                if(ok)
                    return ;
                vis[i]=0;
            }    
        }    
    }
}
int main()
{
    cin>>s;
    memset(vis,0,sizeof(vis));
    n=len=s.length();
    if(n<10)
    {
        for(int i=0;i<len;i++)
            cout<<s[i]<<" ";
            cout<<endl;
    }
    else
    {
        n=(n-9)/2+9;
        dfs(n);
        
    }
}
原文地址:https://www.cnblogs.com/liyexin/p/13771587.html