(DFS)zoj1008-Gnome Tetravex

现在zoj暂时关了,实际上是在scuoj上做的。

题目地址

看起来题目比较复杂,实际上主要需要思维的是如何恰当的剪枝及合适的DFS角度。

问题等价于将n*n个可能相同的方块放到一个n*n的表中,使满足题目要求的条件。由于放的时候是一个个放的,所以可以以此为切入点进行DFS,并且,只需要关注不同方块的种类,这样就可以极大的节约时间(从人做这件事的角度来看,相同的方块就像是相同的积木一样,人关注的只是相同的积木的形状以及个数。)

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 int a[25][4],kind[25],n,kge,b[25][4],cnt=0,m;//a记录不同种类方块各方向的数,kind记录每种种类的个数,kge记录种类数
 5 int dfs(int p)
 6 {
 7     if(p==m)//dfs成功的话,就是进行到第n*n次(这时前0——n*n-1都已经放好)
 8         return 1;
 9     else
10     {
11         for(int i=0;i<kge;i++)
12         {
13             if(kind[i]==0)
14                 continue;
15             else
16             {
17                 if(p%n!=0)//p%n时左侧就没有方块
18                 {
19                     if(b[p-1][1]!=a[i][3])
20                         continue;
21                 }
22                 if(p>=n)//p<n时在最上一行,上面就没有方块
23                 {
24                     if(b[p-n][2]!=a[i][0])
25                         continue;
26                 }
27                 kind[i]--;
28                 for(int j=0;j<4;j++)
29                 {
30                     b[p][j]=a[i][j];
31                 }
32                 if(dfs(p+1))//继续dfs下一个位置
33                 {
34                     return 1;
35                 }
36                 kind[i]++;//如果这样并不行,恢复至之前的状态
37             }
38         }
39         return 0;
40     }
41 }
42 int main()
43 {
44     while(scanf("%d",&n))
45     {
46         kge=0;
47         if(n==0)
48             break;
49         else
50         {
51             int up,left,right,down,i,j;
52             m=n*n;
53             for(i=0;i<m;i++)
54             {
55                 scanf("%d%d%d%d",&up,&right,&down,&left);
56                 for(j=0;j<kge;j++)
57                 {
58                     if(a[j][0]==up&&a[j][1]==right&&a[j][2]==down&&a[j][3]==left)
59                     {
60                         kind[j]++;
61                         break;
62                     }
63                 }
64                 if(j==kge)//整体是对有无与之前的方块相同的判断
65                     {
66                         a[kge][0]=up;
67                         a[kge][1]=right;
68                         a[kge][2]=down;
69                         a[kge][3]=left;
70                         kind[kge]=1;
71                         kge++;
72                     }
73             }
74             if(cnt)
75                 puts("");//注意空行
76             if(dfs(0))
77                 printf("Game %d: Possible\n",++cnt);
78             else
79                 printf("Game %d: Impossible\n",++cnt);
80         }
81     }
82     return 0;
83 }

 

posted @ 2016-11-04 15:05  perplex  阅读(404)  评论(0编辑  收藏  举报