poj入门级搜索专练

 (POJ2488)A Knight's Journey

题目大意很明了,就是找到一个路径让马走完所有的点,不重复不遗漏;思路很容易找到,直接用DFS搜索标记并回溯,一个点一个点作为起点去试;找到后停止;

虽然感觉很简单,做的时候却没那么容易==||   下面是AC代码

View Code
 1 #include<stdio.h>
 2  int dir[8][2]={-2,-1,-2,1,-1,-2,-1,2,1,-2,1,2,2,-1,2,1};   //记录方向
 3  int g,a,b;//g用来记录是否找到解,找到后不再搜索
 4  int vist[26][26],path[26][2];
 5  void find(int i,int j,int k)//i,j是要走的格子,k记录已经走过的步数
 6  {
 7      if(k==a*b)//走完了
 8      {
 9          for(int i=0;i<k;i++)
10          printf("%c%d",path[i][0]+'A',path[i][1]+1);
11          printf("\n");
12          g=1;
13      }
14      else
15      for(int x=0;x<8;x++)//8个方向依次搜索
16      {
17          int n=i+dir[x][0];
18          int m=j+dir[x][1];
19          if(n>=0&&n<b&&m>=0&&m<a&&!vist[n][m]&&!g)
20          {
21              vist[n][m]=1;//标记已走
22              path[k][0]=n,path[k][1]=m;
23              find(n,m,k+1);
24              vist[n][m]=0;//清除标记
25          }
26      }
27  }
28  int main()
29  {
30      int n;
31      scanf("%d",&n);
32      for(int m=0;m<n;m++)
33      {
34          g=0;
35          scanf("%d %d",&a,&b);
36          for(int i=0;i<a;i++)//一个点一个点的尝试
37              for(int j=0;j<b;j++)
38                  vist[i][j]=0;
39          vist[0][0]=1;
40          path[0][0]=0,path[0][1]=0;
41          printf("Scenario #%d:\n",m+1);
42          find(0,0,1);
43          if(!g) printf("impossible\n");
44          printf("\n");
45      }
46      return 0;
47  }

 

POJ3083  Children of the Candy Corn

题目大意:从入口S进到出口E,如果一直按照走左边的路(碰到墙后返回来继续),或一直选择向右走,各自需要多少步;和求最短路(简单BFS)

这道题虽说是一道题,却同时考察了DFS和BFS

当然,这道题的困难之处不在于DFS有多复杂,而在于如何一直向左走或向右走却不受位置的影响,解决办法是设置两个数组顺时针与逆时针,方法如下:

设左上右下为 0, 1, 2, 3
顺时针时,假设当前的前进方向为d, 那么从(d+2)%4,也就是相反方向开始循环,每次
(d+1)%4,遇到第一个能走的就前进。
逆时针时同理,不同的是每次(d-1+4)%4。
下面附上本人比较挫代码
View Code
  1 #include<cstdio>
  2  #include<cstring>
  3  #include<cstdlib>
  4  #include<queue>
  5  #include<string>
  6  #include<stack>
  7  #include<cmath>
  8  #include<cctype>
  9  #include<iostream>
 10  #include<set>
 11  #include<algorithm>
 12  #include<ctime>
 13  #include<vector>
 14  #define mem(a) memset(a,0,sizeof(a))
 15  #define MAXN 1000000007
 16  #define judge(x,y) x>=0&&x<m&&y>=0&&y<n&&map[x][y]!='#'&&!vis[x][y]
 17  using namespace std;
 18  int dir1[4][2]={{-1,0},{0,1},{1,0},{0,-1}};//顺时针
 19  int dir2[4][2]={{0,-1},{1,0},{0,1},{-1,0}};//逆时针
 20  char map[45][45];
 21  bool vis[45][45];
 22  int m,n;
 23  struct node
 24  {
 25      int x,y;
 26      int dist;
 27  };
 28  int step,START_I;
 29  int left_step=0,right_step=0;
 30  
 31  int DFS(int x,int y,int I,int di[][2])//di[][0、1]区别向左还是向右
 32  {
 33      if(map[x][y]=='E')return 1;
 34      int i,j;
 35      for(j=0;j<4;j++)
 36      {
 37          i=(I+j+3)%4;
 38          if(judge(x+di[i][0],y+di[i][1])){
 39              step=DFS(x+di[i][0],y+di[i][1],i,di)+1;
 40              break;
 41          }
 42      }
 43      return step;
 44  }
 45  
 46  int bfs(int x,int y)//BFS返回最小步数
 47  {
 48      mem(vis);
 49      queue<node>q;
 50      node u;
 51      u.x=x;u.y=y;u.dist=0;
 52      vis[u.x][u.y]=true;
 53      q.push(u);
 54      while(!q.empty())
 55      {
 56          u=q.front();
 57          int d=u.dist,i;
 58          if(map[u.x][u.y]=='E')return u.dist;
 59          q.pop();
 60          for(i=0;i<4;i++)
 61          {
 62              node v;
 63              v.x=u.x+dir1[i][0];v.y=u.y+dir1[i][1];
 64              if(judge(v.x,v.y))
 65              {
 66                  vis[v.x][v.y]=true;
 67                  v.dist=d+1;
 68                  q.push(v);
 69              }
 70          }
 71      }
 72      return 0;
 73  }
 74  int main()
 75  {
 76      int cas;
 77      scanf("%d",&cas);
 78      while(cas--)
 79      {
 80          mem(map);mem(vis);
 81          scanf("%d%d",&n,&m);
 82          int i,j,sx,sy;
 83          for(i=0;i<m;i++)
 84          {
 85              scanf("%s",map[i]);
 86              for(j=0;j<n;j++)
 87              if(map[i][j]=='S')sx=i,sy=j;
 88          }
 89  
 90          //一直按向左走时,先找到出口的方向
 91          for(i=0;i<4;i++)
 92              if(judge(sx+dir1[i][0],sy+dir1[i][1]))
 93                  START_I=i;
 94          step=0;
 95          left_step=DFS(sx,sy,START_I,dir1);//DFS搜索
 96  
 97          //向右
 98          for(i=0;i<4;i++)
 99              if(judge(sx+dir2[i][0],sy+dir2[i][1]))
100                  START_I=i;
101          step=0;mem(vis);
102          right_step=DFS(sx,sy,START_I,dir2);
103          printf("%d %d %d\n",left_step,right_step,bfs(sx,sy)+1);
104      }
105      return 0;
106  }

 

 POJ3009  Curling 2.0

题目大意:一个球只能走直线,切只能在碰到石头的时候才能停下来;而被碰到的石头将会消失;

走一次直线只算一步,求最少步数;

这道题呢,颠覆了我以前的思考,总觉得BFS和DFS只能一步一步向旁边走一步,却不知道还可以搜直线,而且一次搜到底部

题目给了一个条件就是当步数打不10时就认为是不能走到了,这复杂度就有了大大的减小;所以直接暴力每条路径搜完也不会超时;

代码:直接每条路搜索完全

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<queue>
 5 #include<string>
 6 #include<stack>
 7 #include<cmath>
 8 #include<cctype>
 9 #include<iostream>
10 #include<set>
11 #include<algorithm>
12 #include<ctime>
13 #include<vector>
14 using namespace std;
15 #define mem(a) memset(a,0,sizeof(a))
16 #define MAXN 1000000007
17 #define judge(x,y) x>=0&&x<h&&y>=0&&y<w&&map[x][y]!=1
18 int map[30][30];
19 int w,h,sx,sy,ex,ey,step,steps,fin;
20 int d[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
21 struct node
22 {
23     int x;int y;
24     int step;
25 };
26 
27 void DFS(int x,int y)
28 {
29     int i;if(step>10)return;
30     for(i=0;i<4;i++)
31     {
32         int nx,ny,ok;
33         ok=0;
34         nx=x+d[i][0],ny=y+d[i][1];
35         while(judge(nx,ny))
36         {
37             ok=1;
38             if(nx==ex&&ny==ey)if(step<steps)steps=step;
39             nx+=d[i][0],ny+=d[i][1];
40         }
41         if(map[nx][ny]==1&&ok)
42         {
43             step++;map[nx][ny]=0;
44             DFS(nx-d[i][0],ny-d[i][1]);
45             step--;map[nx][ny]=1;
46         }
47     }
48 }
49 int main()
50 {
51     while(~scanf("%d%d",&w,&h)&&w&&h)
52     {
53         mem(map);
54         int i,j;
55         for(i=0;i<h;i++)
56         {
57             for(j=0;j<w;j++){
58                 scanf("%d",&map[i][j]);
59                 if(map[i][j]==2)sx=i,sy=j;
60                 if(map[i][j]==3)ex=i,ey=j;
61             }
62         }
63         steps=1000000;
64         step=1;
65         DFS(sx,sy);
66         printf("%d\n",steps>10?-1:steps);
67     }
68     return 0;
69 }

 

 

poj3278Catch That Cow

最水的BFS搜索了。。。。

 在这里对BFS原理还做简单介绍,之后一律不讲

View Code
 1 #include<stdio.h>
 2 #include<string.h>
 3 #define mem(a) memset(a,0,sizeof(a))
 4 int vis[200005],q[200005],d[200005];
 5 int n,k;
 6 void bfs(int x)
 7 {
 8     mem(vis);mem(q);mem(d);
 9     vis[x]=1;
10     int front=0,rear=0;//front指向队列首,rear指向队列尾部
11     q[rear++]=x;//尾部加入一个
12     while(front<rear)
13     {
14         x=q[front++];//取出队列首的元素
15         if(x==k)return ;//如果找到了就返回
16         if(!vis[x-1]&&x>0){vis[x-1]=1;q[rear++]=x-1;d[x-1]=d[x]+1;}//如果x-1没有走过,则加在队列的尾部
17         if(!vis[x+1]&&x<100000){vis[x+1]=1;q[rear++]=x+1;d[x+1]=d[x]+1;}//与上面相似x+1
18         if(!vis[x*2]&&x<=50000){vis[x*2]=1;q[rear++]=2*x;d[x*2]=d[x]+1;}//一样x*2
19     }
20 }
21 int main()
22 {
23     while(~scanf("%d%d",&n,&k))
24     {
25         bfs(n);
26         printf("%d\n",d[k]);
27     }
28     return 0;
29 }

 


 

poj2251Dungeon Master

这个不用多说,最简单的BFS求最短距离,只是改一下方向数组就可以,二维数组改为三维数组

下面是AC代码

对了,下面用的c++队列,其实很简单,就只有几种操作:

先介绍队列的定义   queue<类型名>变量名,如

queue<int>q,queue或queue<node>que;(struct node(结构体类型));

1、 q.front()      取出队首元素

2、   q.empty()    判断是否为空,时空返回1

3、   q.pop()       删除队首元素

4、   q.push(变量)加入变量      

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<queue>
 5 #include<string>
 6 #include<stack>
 7 #include<cmath>
 8 #include<cctype>
 9 #include<iostream>
10 #include<set>
11 #include<algorithm>
12 #include<ctime>
13 #include<vector>
14 using namespace std;
15 #define mem(a) memset(a,0,sizeof(a))
16 #define MAXN 1000000007
17 #define judge(x,y,z) !vis[x][y][z]&&map[x][y][z]!='#'&&x>=0&&x<l&&y>=0&&y<m&&z>=0&&z<n
18 int d[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};
19 bool vis[35][35][35];
20 char map[35][35][35];
21 int l,m,n;
22 struct node
23 {
24     int x,y,z;
25     int step;
26 };
27 int  BFS(int x,int y,int z)
28 {
29     mem(vis);
30     queue<node>q;
31     node u;
32     u.x=x;u.y=y;u.z=z;
33     u.step=0;
34     q.push(u);
35     while(!q.empty())
36     {
37         u=q.front();
38         if(map[u.x][u.y][u.z]=='E')return u.step;
39         q.pop();
40         int i;
41         for(i=0;i<6;i++)
42         {
43             node v;
44             v.x=u.x+d[i][0];v.y=u.y+d[i][1];
45             v.z=u.z+d[i][2];
46             if(judge(v.x,v.y,v.z))
47             {
48                 vis[v.x][v.y][v.z]=true;
49                 v.step=u.step+1;
50                 q.push(v);
51             }
52         }
53     }
54     return 0;
55 }
56 int main()
57 {
58     while(~scanf("%d%d%d%*c",&l,&m,&n))
59     {
60         mem(map);
61         if(!m&&!n&&!l)break;
62         int i,j,k,sx,sy,sz;
63         for(i=0;i<l;i++)
64             for(j=0;j<m;j++){
65                 scanf("%s",map[i][j]);
66                 for(k=0;k<n;k++)
67                 {
68                     if(map[i][j][k]=='S')sx=i,sy=j,sz=k;
69                 }
70             }
71         int step=BFS(sx,sy,sz);
72         if(step)printf("Escaped in %d minute(s).\n",step);
73         else printf("Trapped!\n");
74     }
75     return 0;
76 }


 

poj3414Pots

空杯子倒水问题,这题比较简单,只有两个杯子,最初的时候都是空的,要倒出指定量的水有三种操作:

1、FILL(i)        把第i个杯子装满(i=0,1)

2、DROP(i)      把第i个杯子倒空

3、POUR(i,j)    把i的水倒入到j中,直到j满或i倒完

我的想法:把a->b,b->c,。。。。共6种倒水方法一个一个列出来,而每种都是一样的讨论方法,

虽然很好做,但对于我这样的入门级水手来说还是写不出太好看的代码,所以。。。。

看看吧,看不懂再去看看网上别人的==||

View Code
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<queue>
  5 #include<string>
  6 #include<stack>
  7 #include<cmath>
  8 #include<cctype>
  9 #include<iostream>
 10 #include<set>
 11 #include<algorithm>
 12 #include<ctime>
 13 #include<vector>
 14 using namespace std;
 15 #define mem(a) memset(a,0,sizeof(a))
 16 #define MAXN 1000000007
 17 char op[6][20]={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};
 18 int vis[110][110],fa[110][110],opp[110][110];//0~5->fill a,fill b,drop a,drop b,pour a-b,pour b-a
 19 int sa,sb;
 20 struct pot
 21 {
 22     int a,b;
 23     int step;
 24 };
 25 void print(int a,int b)
 26 {
 27     if(opp[a][b]==-1)return;
 28     else {
 29         print(fa[a][b]/1000,fa[a][b]%1000);
 30         printf("%s\n",op[opp[a][b]]);
 31     }
 32 }
 33 int BFS(int C)
 34 {
 35     mem(vis);mem(fa);mem(opp);
 36     pot u;
 37     u.a=0;u.b=0;u.step=0;
 38     opp[0][0]=-1;
 39     fa[0][0]=0;
 40     vis[0][0]=1;
 41     queue<pot>q;
 42     q.push(u);
 43     while(!q.empty())
 44     {
 45         u=q.front();
 46         q.pop();
 47         if(u.a==C||u.b==C){printf("%d\n",u.step);print(u.a,u.b);return 1;}
 48         pot v=u;
 49         if(u.a!=sa)//是不是没有装满
 50         {v.a=sa;
 51             if(!vis[v.a][v.b]){//是不是没有搜过
 52                 v.step++;
 53                 q.push(v);
 54                 opp[v.a][v.b]=0;
 55                 vis[v.a][v.b]=1;
 56                 fa[v.a][v.b]=u.a*1000+u.b;
 57             }
 58         }v=u;
 59         if(u.b!=sb){v.b=sb;
 60             if(!vis[v.a][v.b]){
 61                 v.step=u.step+1;
 62                 q.push(v);
 63                 opp[v.a][v.b]=1;
 64                 vis[v.a][v.b]=1;
 65                 fa[v.a][v.b]=u.a*1000+u.b;
 66             }
 67         }v=u;
 68         if(u.a){v.a=0;
 69             if(!vis[v.a][v.b]){
 70                 v.step=u.step+1;
 71                 q.push(v);
 72                 opp[v.a][v.b]=2;
 73                 vis[v.a][v.b]=1;
 74                 fa[v.a][v.b]=u.a*1000+u.b;
 75             }
 76         }v=u;
 77         if(u.b){v.b=0;
 78             if(!vis[v.a][v.b]){
 79                 v.step=u.step+1;
 80                 q.push(v);
 81                 opp[v.a][v.b]=3;
 82                 vis[v.a][v.b]=1;
 83                 fa[v.a][v.b]=u.a*1000+u.b;
 84             }
 85         }v=u;
 86         if(u.a){
 87             if(v.a>=sb-u.b&&u.b!=sb){v.a-=(sb-u.b);v.b=sb;}
 88             else if(v.a<sb-u.b){v.a=0;v.b+=u.a;}
 89             if(!vis[v.a][v.b]){
 90                 v.step=u.step+1;
 91                 q.push(v);
 92                 opp[v.a][v.b]=4;
 93                 vis[v.a][v.b]=1;
 94                 fa[v.a][v.b]=u.a*1000+u.b;
 95             }
 96         }v=u;
 97         if(u.b)
 98         {
 99             if(v.b>=sa-u.a&&u.a!=sa){v.b-=(sa-u.a);v.a=sa;}
100             else if(v.b<sa-u.a){v.b=0;v.a+=u.b;}
101             if(!vis[v.a][v.b]){
102                 v.step=u.step+1;
103                 q.push(v);
104                 opp[v.a][v.b]=5;
105                 vis[v.a][v.b]=1;
106                 fa[v.a][v.b]=u.a*1000+u.b;
107             }
108         }
109     }
110     return 0;
111 }
112 int main()
113 {
114     int c;
115     while(~scanf("%d%d%d",&sa,&sb,&c)&&c)
116     {
117         int ok=BFS(c);
118         if(!ok)printf("impossible\n");
119     }
120     return 0;
121 }

 

POJ1321棋盘问题

题目大意很明确,就是求k个棋子放在一盘棋上,其中有些可以放,有些不可以;问有多少种方法使得每行每列只有一个棋子。

由于题目给的数据范围比较小(n<=8),所以可以用深搜(数据较大的话可以去百度参考状态压缩),还是采用标记搜索去除标记的方法,只是要注意边界条件以及回溯的条件;思路已经在代码里了:看看吧。。。

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<queue>
 5 #include<string>
 6 #include<stack>
 7 #include<cmath>
 8 #include<cctype>
 9 #include<iostream>
10 #include<set>
11 #include<algorithm>
12 #include<ctime>
13 #include<vector>
14 using namespace std;
15 #define mem(a) memset(a,0,sizeof(a))
16 #define MAXN 100000007
17 int num[9],number[9][9],n,k;//num记录每一行的可行数,number记录可行所在的列 
18 char map[9];
19 bool vis[9];
20 int method,put;
21 void DFS(int cur)
22 {
23     if(k==put){method++;return;}//如果找到了(当然也包括第k个放在最后一行的情况) 
24     if(cur==n||k-put>n-cur)return ;//如果超出边界或剩下的行数比需要放下的少 
25     int i;
26     if(!num[cur]){DFS(cur+1);return;}//如果一行为空
27     int flag=1;
28     for(i=0;i<num[cur];i++)
29     {
30         if(!vis[number[cur][i]]){
31             put++;vis[number[cur][i]]=true;//放一个
32             DFS(cur+1);
33             put--;vis[number[cur][i]]=false;//不放
34         }
35     }
36     DFS(cur+1); //这一行不放,直接搜索下一行 ,但是只能搜一次,不然会重复  
37 }
38 int main()
39 {
40     while(~scanf("%d%d%*c",&n,&k))
41     {
42         if(n==-1&&k==-1)break;
43         int i,j;mem(number);mem(num);
44         for(i=0;i<n;i++){
45             scanf("%s",map);
46             for(j=0;j<n;j++)
47                 if(map[j]=='#')number[i][num[i]++]=j;//记录每一行的个数与所在的列数 
48         }
49         mem(vis);put=0;method=0;
50         DFS(0);
51         printf("%d\n",method);
52     }
53 }

其中我加了一句(k-put>n-cur) 24行,时间花了16Ms,如果删去,也可以过,时间却要花上63Ms,所以优化优化再优化。。。。

 

POJ1426Find The Multiple

题目的意思就是给你一个数n,让你找到一个它的倍数只由1和0组成。(任何一个都可以,Special Judge)

最开始自己怕数据太大,就用数组存放1和0,再一一判断,结果TLE,实在是没有办法了,在网上搜寻别人的代码,看了看discuss

发现一个奇葩的代码:我也不知道怎么评价这代码了,只能说我Orz。。。。。

View Code
 1 #include<stdio.h>
 2  #include <stdlib.h>
 3  #include <iostream>
 4  int s=0;
 5  
 6  using namespace std;
 7  void bag(__int64 p,int n,int k)
 8  {
 9      if(s==1||k==20)
10          return;
11      if(p%n==0)
12      {
13          printf("%I64u\n",p);
14          s=1;
15      }
16      else
17      {
18          bag(10*p,n,k+1);
19          bag(10*p+1,n,k+1);        
20      }
21  }
22  
23  int main()
24  {
25      int n;
26      while(cin>>n,n)
27      {
28          s=0;
29          bag(1,n,1);
30      }
31      return 0;
32  }

 

 POJ3126Prime Path

题目大意就是给两个四位的素数a,b,每次替换a的一个数位,让a变到b,但是每次替换中所生成的新四位数也必须是素数。求最少要多少步。
简单的BFS直接替换每个数位即可。

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<queue>
 5 #include<string>
 6 #include<stack>
 7 #include<cmath>
 8 #include<cctype>
 9 #include<iostream>
10 #include<set>
11 #include<algorithm>
12 #include<ctime>
13 #include<vector>
14 using namespace std;
15 #define mem(a) memset(a,0,sizeof(a))
16 #define MAXN 1000000007
17 int vis[10000];
18 int m;
19 struct number
20 {
21     int num,step;
22 };
23 int isprime(int n)
24 {
25     int i;
26     for(i=2;i*i<=n;i++)if(n%i==0)return 0;
27     return 1;
28 }
29 int BFS(int target)
30 {
31     mem(vis);
32     number u;
33     u.num=m;u.step=0;
34     queue<number>q;
35     q.push(u);
36     while(!q.empty())//队列不为空时
37     {
38         u=q.front();//取队列首元素
39         q.pop();//删除队列首元素
40         if(u.num==target)return u.step;
41         int i,j;
42         for(i=3;i>=0;i--)//从最高位开始
43         {
44             double p=(double)pow((double)10,(int)i);
45             int x=(u.num/(int)p)%10;
46             for(j=0;j<10;j++)
47             {
48                 if(i==3&&j==0)continue;//最高位不能为0
49                 int y=u.num+(j-x)*p;//判断下一个数
50                 if(!vis[y]&&isprime(y))//如果没有搜索过且是素数
51                 {
52                     vis[y]=1;
53                     number v;v.num=y;v.step=u.step+1;
54                     q.push(v);
55                 }
56             }
57         }
58     }
59     return -1;
60 }
61 int main()
62 {
63     int n;
64     scanf("%d",&n);
65     while(n--)
66     {
67         int target;
68         scanf("%d%d",&m,&target);
69         int ok=BFS(target);
70         if(ok!=-1)printf("%d\n",ok);
71         else printf("Impossible\n");
72     }
73     return 0;
74 }

 

POJ2676Sudoku

数独,提议就不用解释了吧。。。。

我用row[k][i]表示第k行是否已经有数i

col[k][i]表示第k列是否已经有数i

而sq[k][i]表示第k个九宫格是否有数i(这里k=(x/3)*3+(y/3),可以想想为什么)

从0,0 依次搜到8,8  DFS依次往下,看代码:(已有注释)

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<queue>
 5 #include<string>
 6 #include<stack>
 7 #include<cmath>
 8 #include<cctype>
 9 #include<iostream>
10 #include<set>
11 #include<algorithm>
12 #include<ctime>
13 #include<vector>
14 using namespace std;
15 #define mem(a) memset(a,0,sizeof(a))
16 #define MAXN 100000007
17 bool col[9][9],row[9][9],sq[9][9],vis[9][9];
18 int map[9][9];
19 bool Isfind;
20 void print()
21 {
22     int i,j;
23     for(i=0;i<9;i++){
24         for(j=0;j<9;j++)
25             printf("%d",map[i][j]+1);
26         printf("\n");
27     }
28 }
29 void DFS(int x,int y)
30 {
31     int u=x*9+y+1,i;
32     if(x==9){//全部都满足了
33         Isfind=true;//标记已经找到
34         print();//打印
35     }
36     if(Isfind)return ;//找到了就不用再搜索
37     if(map[x][y]!=-1){
38         DFS(u/9,u%9);//如果本来就已经有数,直接搜索下一个
39         return;
40     }
41     for(i=0;i<9&&!Isfind;i++)
42     {
43         int k=(x/3)*3+y/3;
44         if(!row[x][i]&&!col[y][i]&&!sq[k][i])
45         {
46             row[x][i]=col[y][i]=sq[k][i]=true;map[x][y]=i;//标记并把map赋值
47             DFS(u/9,u%9);                                   //搜下一个
48             row[x][i]=col[y][i]=sq[k][i]=false;map[x][y]=-1;//清除标记
49         }
50     }
51 }
52 int main()
53 {
54     int i,j,cas;char q;
55     scanf("%d",&cas);
56     while(cas--){
57         mem(vis);mem(map);
58         mem(row);mem(col);mem(sq);
59         for(i=0;i<9;i++)
60             for(j=0;j<9;j++){
61                 cin>>q;
62                 map[i][j]=q-'1';
63                 if(q-'0')
64                     row[i][q-'1']=col[j][q-'1']=sq[(i/3)*3+(j/3)][q-'1']=true;
65             }
66         Isfind=false;
67         DFS(0,0);
68     }
69 }

这行代码花了563毫秒,然后如果从8,8搜到0,0结果就只有16毫秒,代码在下面:(就稍稍改了一下)

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<queue>
 5 #include<string>
 6 #include<stack>
 7 #include<cmath>
 8 #include<cctype>
 9 #include<iostream>
10 #include<set>
11 #include<algorithm>
12 #include<ctime>
13 #include<vector>
14 using namespace std;
15 #define mem(a) memset(a,0,sizeof(a))
16 #define MAXN 100000007
17 bool col[9][9],row[9][9],sq[9][9],vis[9][9];
18 int map[9][9];
19 bool Isfind;
20 void print()
21 {
22     int i,j;
23     for(i=0;i<9;i++){
24         for(j=0;j<9;j++)
25             printf("%d",map[i][j]+1);
26         printf("\n");
27     }
28 }
29 void DFS(int x,int y)
30 {
31     int u=x*9+y-1,i;
32     if(x==-1){
33         Isfind=true;
34         print();
35     }
36     if(Isfind)return ;
37     if(map[x][y]!=-1){
38         DFS(u/9,u%9);
39         return;
40     }
41     for(i=0;i<9&&!Isfind;i++)
42     {
43         int k=(x/3)*3+y/3;
44         if(!row[x][i]&&!col[y][i]&&!sq[k][i])
45         {
46             row[x][i]=col[y][i]=sq[k][i]=true;map[x][y]=i;
47             DFS(u/9,u%9);
48             row[x][i]=col[y][i]=sq[k][i]=false;map[x][y]=-1;
49         }
50     }
51 }
52 int main()
53 {
54     int i,j,cas;char q;
55     scanf("%d",&cas);
56     while(cas--){
57         mem(vis);mem(map);
58         mem(row);mem(col);mem(sq);
59         for(i=0;i<9;i++)
60             for(j=0;j<9;j++){
61                 cin>>q;
62                 map[i][j]=q-'1';
63                 if(q-'0'){
64                     row[i][q-'1']=true;
65                     col[j][q-'1']=true;
66                     sq[(i/3)*3+(j/3)][q-'1']=true;
67                 }
68             }
69         Isfind=false;
70         DFS(8,8);
71     }
72 }

 

posted @ 2013-04-10 21:31  再见~雨泉  阅读(5210)  评论(1编辑  收藏  举报