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 }

 

posted @ 2017-05-30 14:23  狡啮之仰  阅读(434)  评论(0编辑  收藏  举报