51nod 1384 可重集的全排列
对于1231,121,111等有重复的数据,我们怎么做到生成全排列呢
实际上,对于打标记再释放标记的这种方法,如果一开始第一层递归访问过1那么你再访问
就会完全重复上一次1开头的情况,那么递归地考虑这件事,我们发现不需要重复相同的开头
但这样可能会重复一个数字过多次数,比如121,第一层2,第二层可能是2,第三层可能也是2
那么我们怎么解决这个呢,一个笨办法是统计原数组该值出现几次,现有生成的数列里出现了几次,
那么比较一下大小,我们就知道能不能放
关于不放重复开头这件事,我们可以对原序列排序,于是相同的值相邻,那么我们在实现中,每次跳过相同的一段即可
附上代码,由于输出量巨大,所以...cstdio TLE,stdio.h AC
1 #include <stdio.h> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 char s[100]; 6 int num[100],sz,A[100]; 7 void dfs(int cur){ 8 if(cur==sz){ 9 for(int i=0;i<sz;++i) printf("%d",A[i]);printf("\n"); 10 } 11 else for(int i=0;i<sz;++i){ 12 if(!i||(num[i]!=num[i-1])){ 13 int c1=0,c2=0; 14 for(int j=0;j<cur;++j) if(num[i]==A[j]) c1++; 15 for(int j=0;j<sz;++j) if(num[i]==num[j]) c2++; 16 if(c1<c2){ 17 A[cur]=num[i];dfs(cur+1); 18 } 19 } 20 } 21 } 22 int main(){ 23 scanf("%s",s); 24 sz=strlen(s); 25 for(int i=0;i<sz;++i) num[i]=s[i]-'0'; 26 sort(num,num+sz); 27 dfs(0); 28 return 0; 29 }