迭代加深搜索:POJ3921

 自认为简单的搜索还是可以的,但是经过了这道题过后,我彻底否定自己了!这道题让我看到了搜索的境界:DFS(迭代)+BFS。

    以前我一直以为图论的题只能用图论的算法来做,而我做不出来,肯定是图论的有些算法没学习好!这道题让我看到了:图论算法的本质是搜索。以前似乎在哪里听到这样的说法,但是没注意,就算注意到了也没有领悟到!回头再写迷宫的时候,发现其实迷宫其实也可以转化成图来进行搜索。

    这道题的思路是这样的:先用bfs找到一条最短路,然后枚举删除每个点。删除点的时候,可以用迭代加深。先枚举所有删除K个点的情况,如果无解,则枚举删除K+1个点的情况!

  

  
  
  
  
  1. #include<stdio.h> 
  2. #include<string.h> 
  3. #define MM 4010 
  4. #define MN 100 
  5. struct aaa{ 
  6.     int s,f,next; 
  7. }; 
  8. aaa edge[MM]; 
  9. int head[MN],now; 
  10.  
  11. int n,m,k; 
  12.  
  13. bool rem[MN];//false表示该点没删除,true表示该删除了 
  14. int path[MN]; 
  15. int cpath[MN][MN]; 
  16. int que[MN]; 
  17.  
  18.  
  19. int ite;//表示迭代次数 
  20. int finds;//表示是否找到解 
  21. void init(){ 
  22.     memset(head,0,sizeof(head)); 
  23.     now=0; 
  24.  
  25. void addEdge(int s,int f){ 
  26.     now++;edge[now].s=s;edge[now].f=f;edge[now].next=head[s];head[s]=now; 
  27. //在有向图中利用广度优先搜索找路 
  28. void bfs(){ 
  29.     int lp,rp; 
  30.     memset(path,0,sizeof(path)); 
  31.     lp=rp=0; 
  32.     que[rp++]=1; 
  33.     //找与1相连的点 
  34.     while(lp<rp){//队列不为空 
  35.         int v=que[lp++]; 
  36.         for(int idx=head[v];idx;idx=edge[idx].next){ 
  37.             if(!rem[edge[idx].f]&&path[edge[idx].f]==0){//确实,这个挺巧妙的 能过滤一些边,还能避免环的出现 
  38.                 que[rp++]=edge[idx].f; 
  39.                 path[edge[idx].f]=edge[idx].s; 
  40.                 if(edge[idx].f==n)break
  41.             } 
  42.         } 
  43.         if(path[n])break
  44.     } 
  45. void dfs(int deep){ 
  46.     if(finds)return;//如果已经找到就不用再找了 
  47.     bfs();//找一条路 
  48.     if(path[n]==0){//如果不可到达,则不用找了 
  49.         finds=true
  50.         return
  51.     } 
  52.     int lpos=-1; 
  53.     int v=n; 
  54.     while(v){ 
  55.         cpath[deep][++lpos]=v; 
  56.         v=path[v]; 
  57.     } 
  58.     if(lpos>k){//找到的最短路大小 k,找到了,不用找了 
  59.         finds=true
  60.         return
  61.     } 
  62.     if(deep>ite)return;//如果深度到了,也不用找了 
  63.     for(int i=1;i<lpos;i++){ 
  64.         rem[cpath[deep][i]]=true
  65.             dfs(deep+1); 
  66.         rem[cpath[deep][i]]=false
  67.     } 
  68.  
  69. int make(){ 
  70.     finds=false
  71.     for(int i=0;i<=n;i++){ 
  72.         ite=i; 
  73.         memset(rem,0,sizeof(rem)); 
  74.         dfs(1); 
  75.         if(finds)return i; 
  76.     } 
  77.     return n; 
  78. int main(){ 
  79.     while(1){ 
  80.         scanf("%d %d %d",&n,&m,&k); 
  81.         if(n==0&&m==0&&k==0)break
  82.         int s,f; 
  83.         init(); 
  84.         for(int i=0;i<m;i++){ 
  85.             scanf("%d %d",&s,&f); 
  86.             addEdge(s,f); 
  87.         } 
  88.         printf("%d\n",make()); 
  89.     } 
  90.     return 0; 

 

 

 
                                                                                                                                                                                               

你可能感兴趣的:(搜索,POJ3921)