该题是找满足条件的摆法,直接DFS会超时,关键是压缩存储,同一种正方形只存一次,再DFS,然后搜到一种成功的就要退出,不要把所有可能的摆法都搜完,不然也会超时。初始化种类数不要忘记。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <cstdio> 2 #include <cstring> 3 bool flag ; //成功标志 4 int n,kinds; //正方形的个数为n*n,种类为kinds 5 struct square 6 { 7 int top,bottom,left,right; 8 int num; //该类正方行的个数 9 } rect[26];//记录每个正方形的状况 10 int map[26] ;//正方形的摆法 11 //铺第x个正方形 12 void dfs(int x) 13 { 14 int i; // 循环变量 15 if(x == n*n) //成功标志 16 { 17 flag = true ; 18 return ; 19 } 20 if(flag) return ; //已找到一种正确的摆法,停止搜索,重要 21 for(i=0 ; i < kinds; i++) 22 { 23 if((rect[i].num != 0) && //判断是否可以摆这类正方形 24 (x%n == 0 || rect[i].left == rect[map[x-1]].right)&& 25 (x/n == 0 ||rect[i].top == rect[map[x-n]].bottom) ) 26 { 27 rect[i].num--; //可以,用掉正方形一个 28 map[x]= i; 29 dfs(x+1); 30 rect[i].num++; //未成功,换下一种,正方形数量加回来 31 } 32 } 33 } 34 int main() 35 { 36 // freopen("in.cpp","r",stdin); 37 int i,k; 38 bool showed; //标记是否出现新类型的正方形 39 int ser = 0; //序列号 40 struct square temp; //读正方形 41 temp.num = 1; 42 while(true) 43 { 44 kinds = 0; //初始化,重要 45 flag = false; 46 scanf("%d",&n); 47 if(n == 0 ) break; 48 ser++; 49 if(ser > 1) puts(""); 50 for(i = 0; i < n*n; i++) 51 { 52 scanf("%d%d%d%d",&temp.top, 53 &temp.right,&temp.bottom,&temp.left); 54 showed = true; 55 for(k = 0; k < kinds; k++) 56 { 57 if(rect[k].bottom== temp.bottom 58 &&rect[k].top == temp.top 59 &&rect[k].left == temp.left 60 &&rect[k].right == temp.right) 61 { 62 showed = false; //未出现新类型 63 rect[k].num++; 64 break; 65 } 66 } 67 if(showed)//出现新类型 68 { 69 rect[kinds] = temp; 70 kinds++; 71 } 72 } 73 dfs(0);//从第0个铺起 74 if(flag == true) 75 printf("Game %d: Possible\n",ser); 76 else 77 printf("Game %d: Impossible\n",ser ); 78 } 79 return 0; 80 }