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