洛谷 P1061 Jam的计数法
题解:
相关变量解释:
1 int s,t,w; 2 int tot=0;//最多输出五组 3 int maxNum[maxn];//maxNum[i] : i 位置可以达到的最大值 4 char letter[maxn];
深搜步骤:
(1):预处理出num[ ],maxNum[ ]
1 for(int i=1;i <= w;++i) 2 num[i]=letter[i-1]-'a'+1;//将单词转换成数字 3 for(int i=w;i >= 1;--i) 4 maxNum[i]=t--;//求出i位置可达到的最大值
(2):从w开始往前遍历,找到数值可以变大的位置,在通过Dfs( )求出由于当前位置影响而满足条件的Jam数
1 int index=w; 2 while(index >= 1)//从后往前遍历 3 { 4 while(num[index] < maxNum[index])//判断当前位置是否可以变得更大 5 { 6 num[index]++; 7 Dfs(index,index+1,num);//求出受当前位置变大的影响的Jam数 8 } 9 index--; 10 }
(3):Dfs( )
1 void Dfs(int start,int curPos,int num[]) 2 { 3 if(tot == 5) 4 return ; 5 //curPos == w+1 作用 : 特判index == 1的情况 6 if(curPos == w || curPos == w+1) 7 { 8 if(curPos == w)//特判 9 num[w]=num[w-1]+1; 10 while(num[w] <= maxNum[w])//判断w位置的数是否可以变大 11 { 12 Print(num);//打印答案 13 tot++; 14 if(tot == 5) 15 return ; 16 num[w]++; 17 } 18 int prePos=w-1;//回溯,查找w位置之前,start位置之后第一个变大的位置 19 while(prePos > start && num[prePos] == maxNum[prePos]) 20 prePos--; 21 if(prePos > start)//找到 22 { 23 num[prePos]++; 24 Dfs(start,prePos+1,num); 25 } 26 return ; 27 } 28 num[curPos]=num[curPos-1]+1; 29 Dfs(start,curPos+1,num); 30 }
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn=30; 5 6 int s,t,w; 7 int tot=0;//最多输出五组 8 int maxNum[maxn];//maxNum[i] : i 位置可以达到的最大值 9 char letter[maxn]; 10 11 void Print(int num[]) 12 { 13 for(int i=1;i <= w;++i) 14 printf("%c",num[i]-1+'a'); 15 printf("\n"); 16 } 17 void Dfs(int start,int curPos,int num[]) 18 { 19 if(tot == 5) 20 return ; 21 if(curPos == w || curPos == w+1) 22 { 23 if(curPos == w) 24 num[w]=num[w-1]+1; 25 while(num[w] <= maxNum[w]) 26 { 27 Print(num); 28 tot++; 29 if(tot == 5) 30 return ; 31 num[w]++; 32 } 33 int prePos=w-1; 34 while(prePos > start && num[prePos] == maxNum[prePos]) 35 prePos--; 36 if(prePos > start) 37 { 38 num[prePos]++; 39 Dfs(start,prePos+1,num); 40 } 41 return ; 42 } 43 num[curPos]=num[curPos-1]+1; 44 Dfs(start,curPos+1,num); 45 } 46 void Solve() 47 { 48 int num[maxn]; 49 for(int i=1;i <= w;++i) 50 num[i]=letter[i-1]-'a'+1;//将单词转换成数组 51 for(int i=w;i >= 1;--i) 52 maxNum[i]=t--;//求出i位置可达到的最大值 53 int index=w; 54 while(index >= 1) 55 { 56 while(num[index] < maxNum[index]) 57 { 58 num[index]++; 59 Dfs(index,index+1,num); 60 } 61 index--; 62 } 63 } 64 int main() 65 { 66 scanf("%d%d%d",&s,&t,&w); 67 scanf("%s",letter); 68 Solve(); 69 }
大神Dfs()精简代码:
https://rainman.blog.luogu.org/solution-p1061
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int s,t,w,c; 5 int a[30],cnt; 6 7 inline void output() 8 { 9 for(int i=1;i<=w;i++) 10 cout<<(char)('a'+a[i]-1); 11 cout<<endl; 12 } 13 14 void dfs(int pos,int step) 15 { 16 if(pos==0) 17 return; 18 if(step == 6) 19 return; 20 if(a[pos] < t && a[pos] < a[pos+1]-1) 21 { 22 a[pos]++; 23 for(int i=pos+1;i<=w;i++) 24 a[i]=a[i-1]+1; 25 output(); 26 dfs(w,step+1); 27 } 28 else 29 dfs(pos-1,step); 30 } 31 32 int main() 33 { 34 cin>>s>>t>>w; 35 fflush(stdin); 36 while((c=getchar())!=EOF) 37 { 38 int temp=c-'a'+1; 39 if(temp>=1&&temp<=26) 40 a[++cnt]=temp; 41 } 42 a[w+1]=0x7f; 43 dfs(w,1); 44 return 0; 45 }