地址:​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);

}
}