hdu 2610 2611 dfs的判重技巧
对于全排列枚举的数列的判重技巧
1:如果查找的是第一个元素 那么 从0开始到当前的位置看有没有出现过这个元素 出现过就pass
2: 如果查找的不是第一个元素 那么 从查找的子序列当前位置的前一个元素对应原序列的位置一直到查到到元素的位置看是否出现过。,。 出现过就pass
2610
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; //len:搜索的长度,count:记录有多少个串了 int n,p,len,count_num; int num[1001]; //做一个标记,如果一个短的串都不能够找到, //那么就长的串就更不可能找到了,这里的一个巧妙地剪枝如果没用就会超时 bool flag; typedef struct { int n,pos; }Tem; Tem tem[1001]; //若在产生序列的前一个数字到当前这个数字中, //出现等于num[e]的,那么说明之前已经有序列选择了num[e], bool check(int s,int e) { for(int i = s+1; i < e; i++) if(num[i]==num[e])return false; return true; } void print_sequence(int length) { for(int i = 0; i < length-1;i++) cout<<tem[i].n<<" "; cout<<tem[length-1].n<<endl; } //dep:搜索的深度,也就是目前搜索到子串的长度 //pos: 当前搜索的位置 void dfs(int dep,int pos) { if(count_num >= p)return; //搜索到了 if(dep==len) { count_num++; flag = true; print_sequence(len); //已经搜索到符合的字串了 return; } for(int i=pos;i<n;i++) { if((dep!=0&&tem[dep-1].n<=num[i])||dep==0) { if(dep==0&&!check(-1,i))//当是第一个元素的时候 continue; if(dep!=0&&!check(tem[dep-1].pos,i))//不是第一个元素的时候 continue; tem[dep].n = num[i]; tem[dep].pos = i; dfs(dep+1,i+1); } } return; } int main() { while(cin>>n>>p) { for(int i=0;i<n;i++) cin>>num[i]; count_num = 0; for(int i = 1;i < n;i++) { flag=false; len = i; dfs(0,0); if(count_num>=p||!flag)break; } cout<<endl; } return 0; }
2611
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 101 using namespace std; struct node { int data,pos; }fuck[maxn]; int n,m,cnt,len,liner[maxn]; int cmp(node a,node b) { if(a.data==b.data) return a.pos<b.pos; else return a.data<b.data; } void dfs(int dep,int pos,int prelpos) { if(cnt>m) return; if(dep==len) { cnt++; if(cnt>m) return; for(int i=0;i<dep;i++) { if(i==0) cout<<liner[i]; else cout<<' '<<liner[i]; } cout<<endl; return ; } int pre,f=0;//对一层内的数的判重 pre 用来记录前一次出现的数(每次都要更新,, 这里错了一次) for(int i=pos;i<=n;i++) { if(fuck[i].pos>prelpos) { if(f==0)//先初始化f为0 第一次的时候用来记录 { f=-1; pre=fuck[i].data; } else if(pre==fuck[i].data) continue;//应为是排好序的 所以 同层里面 用过的就直接 continue pre=fuck[i].data; liner[dep]=fuck[i].data; dfs(dep+1,i+1,fuck[i].pos); if(cnt>m) return; } } } int main() { while(cin>>n>>m) { for(int i=1;i<=n;i++) { cin>>fuck[i].data; fuck[i].pos=i; } cnt=0; sort(fuck+1,fuck+1+n,cmp); for(int i=1;i<n;i++) { len=i; dfs(0,1,0); if(cnt>m) break; } cout<<endl; } return 0; }