Feasible pruning
Cut down unnecessary subtrees on the search tree through some judgment. Sometimes, we will find that the subtree state corresponding to a node is not the result we want, so we don't need to search this branch. Cutting off this subtree is pruning.
Once the final solution of some states can not be found in any case, it can be pruned.
Achieve feasibility pruning
/* Select 8 of the 30 numbers from 1 to 30 to make his sum 200 */ #include <iostream> using namespace std; int n=30,k=8,sum=200,ans; int a[100]; void dfs(int i,int cnt,int s){ if(cnt>k){ return; } if(s>sum){ return; } if(i==n){ if(cnt==k&&s==sum){ ans++; } return; } dfs(i+1,cnt,s); dfs(i+1,cnt+1,s+a[i]); } int main() { for(int i=0;i<n;i++){ a[i]=i+1; } dfs(0,0,0); cout<<ans<<endl; } // namespace std;
The implementation speed is very fast.
Optimal pruning
For a class of problems with optimal solutions, optimality pruning can usually be used. For example, when solving the shortest path of maze, if it is found that the current number of steps has exceeded the current optimal solution, the search from the current state is redundant, because it will never find a better solution. Through such pruning, a large number of redundant calculations can be saved.
In addition, in the process of searching whether there is a feasible solution, once a set of feasible solutions are found, all the subsequent searches do not have to be carried out, which is a special case of optimality pruning. (variable of bool type)
Using dfs to realize the shortest path of maze
Pruning: when the number of steps is greater than the answer, there is no need to go back, so prune
#include <iostream> using namespace std; int n,m,ans=1000000; char maze[100][100]; bool vis[100][100]; int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}}; bool in(int x,int y){ return 0<=x&&x<n&&0<=y&&y<m; } void dfs(int x,int y,int step){ if(step>=ans){ return; } if(maze[x][y]=='T'){ ans=step; return; } vis[x][y]=true; for(int i=0;i<4;i++){ int tx=x+dir[i][0]; int ty=y+dir[i][1]; if(in(tx,ty)&&!vis[tx][ty]&&maze[tx][ty]!='#'){ dfs(tx,ty,step+1); } } vis[x][y]=false; } int main() { cin>>n>>m; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ cin>>maze[i][j]; } } int x,y; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(maze[i][j]=='S'){ x=i,y=j; } } } dfs(x,y,0); cout<<ans<<endl; } // namespace std;
Repetitive pruning
It is specified that the position of the selected number is incremented. During the search, a parameter is used to record the position of the last selected number. Then we start to select after this number, so that the last selected scheme will not be repeated.
Of course, the efficiency of search is also higher than that of direct binary enumeration.
#include <iostream> using namespace std; int a[40]; bool xuan[40]; int n,k,sum,ans; void dfs(int s,int cnt,int pos){ if(s>sum||cnt>k){ return; } if(s==sum&&cnt==k){ ans++; } for(int i=pos;i<n;i++){ if(!xuan[i]){ xuan[i]=1; dfs(s+a[i],cnt+1,i+1); xuan[i]=0; } } } int main(){ n=30; k=8; sum=200; for(int i=0;i<n;i++){ a[i]=i+1; } ans=0; dfs(0,0,0); cout<<ans<<endl; return 0; }
Parity pruning
Example of pruning: detonating a bomb
#include <iostream> using namespace std; int n,m,ans; bool row[100],col[100]; char maze[100][100]; void dfs(int x,int y){ maze[x][y]='0'; if(!row[x]){ row[x]=true; for(int j=0;j<m;j++){ if(maze[x][j]=='1'){ dfs(x,j); } } } if(!col[y]){ col[y]=true; for(int i=0;i<n;i++){ if(maze[i][y]=='1'){ dfs(i,y); } } } } int main() { cin>>n>>m; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ cin>>maze[i][j]; } } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(maze[i][j]=='1'){ ans++; dfs(i,j); } } } cout<<ans<<endl; } // namespace std;