1 /*
2 题意:给出一个边长为S的六边形,再给出n种边长不同的三角形,所有的长度均为整型,问这n种三角形是否
3 能够拼成这个六边形。
4
5 题解:DFS+剪枝
6 这题的关键是图的表示方法以及剪枝,图我用了一个二维数组直接表示:
7 111111111111111111111
8 111110000000000011111
9 111100000000000001111
10 111000000000000000111
11 110000000000000000011
12 100000000000000000001
13 100000000000000000001
14 110000000000000000011
15 111000000000000000111
16 111100000000000001111
17 111110000000000011111
18 111111111111111111111
19 然后就是DFS,自上而下,从左往右,对每个最小的三角形进行搜索,按照顺序遍历能使得搜索的数量会少一
20 点,每一次对当前位置判断并将正三角形和倒三角形分别加入尝试;
21 剪枝:
22 大于S的三角形忽略,取模为0的两个三角形只需选边较短的,从短边的三角形开始尝试,如果某个三角形边长
23 能够整除S,那么该三角形可以直接组成六边形
24 */
25 #include <cstdio>
26 #include <cstring>
27 #include <algorithm>
28
29 using namespace std;
30
31 int stype[15];
32 int S,n;
33 bool gra[105][105];
34
35 bool dfs(int x, int y)
36 {
37 for(int i=0; i<=2*S+1; i++)
38 {
39 for(int j=0; j<=4*S; j++)
40 printf("%d",gra[i][j]);
41 printf("\n");
42 }
43 if (x > 2*S)
44 return true;
45
46 // 判断是否在图上
47 if (x <= S && y > 3*S+x-1)
48 return dfs(x+1,S-x);
49 if (x > S && y > 4*S-1-(x-S-1))
50 return dfs(x+1,x+1-S);
51 if (gra[x][y]) // 超过图上则换行
52 return dfs(x,y+1);
53
54 if (((x+y)&1) != ((1+S)&1)) // 三角形底在上
55 {
56 for(int i=0; i<n; i++)
57 {
58 bool flag = true;
59 for(int j=0; j<2*stype[i]-1; j++)
60 if (gra[x][y+j])
61 {
62 flag = false;
63 break;
64 }
65 if (flag)
66 {
67 for(int j=0; j<stype[i]; j++)
68 if (gra[x+j][y+j] || gra[x+j][y+2*stype[i]-2-j])
69 {
70 flag = false;
71 break;
72 }
73 }
74 if (flag) // 可以访问
75 {
76 for(int j=0; j<stype[i]; j++)
77 for(int k=0; k<2*stype[i]-1-2*j;k++)
78 gra[x+j][y+j+k] = true;
79 if (!dfs(x,y+1))
80 for(int j=0; j<stype[i]; j++)
81 for(int k=0; k<2*stype[i]-1-2*j;k++)
82 gra[x+j][y+j+k] = false;
83 else
84 return true;
85 }
86 }
87 }
88 else // 底在下
89 {
90 for(int i=0; i<n; i++)
91 {
92 bool flag = true;
93 for(int j=0; j<stype[i]; j++)
94 {
95 if (gra[x+j][y+j] || gra[x+j][y-j])
96 {
97 flag = false;
98 break;
99 }
100 }
101 if (flag)
102 {
103 for(int j=0; j<stype[i]; j++)
104 for(int k=0; k<j+1; k++)
105 gra[x+j][y+k] = gra[x+j][y-k] = true;
106 if (!dfs(x,y+1))
107 for(int j=0; j<stype[i]; j++)
108 for(int k=0; k<j+1; k++)
109 gra[x+j][y+k] = gra[x+j][y-k] = false;
110 else
111 return true;
112 }
113 }
114 }
115 return false;
116 }
117
118 int main(void)
119 {
120 int t;
121 scanf("%d",&t);
122
123 while (t--)
124 {
125 scanf("%d%d",&S,&n);
126 for(int i=0; i<n; i++)
127 scanf("%d",&stype[i]);
128 memset(gra,false,sizeof(gra));
129
130 for(int i=0; i<=4*S; i++)
131 gra[0][i] = gra[i][0] = gra[2*S+1][i] = gra[i][4*S] = true;
132
133 for(int i=1; i<=S-1; i++)
134 for(int j=1; j<=i; j++)
135 gra[S-i][j] = gra[S-i][4*S-1-(j-1)] = gra[S+1+i][j] = gra[S+1+i][4*S-1-(j-1)] = true;
136
137 sort(stype,stype+n);
138
139 bool tflag = false;
140 for(int i=0; i<n; i++)
141 {
142 if (S % stype[i] == 0)
143 {
144 printf("YES\n");
145 tflag = true;
146 break;
147 }
148 }
149 for(int i=0; i<n; i++)
150 {
151 if (stype[i] > S)
152 {
153 n = i;
154 break;
155 }
156 }
157
158 for(int i=0; i<n-1; i++)
159 {
160 for(int j=i+1; j<n; j++)
161 {
162 if (stype[j] % stype[i] == 0)
163 {
164 for(int k=j+1; k<n; k++)
165 stype[k-1] = stype[k];
166 n--;
167 j--;
168 }
169 }
170 }
171
172 if (tflag)
173 continue;
174
175 if (dfs(1,S))
176 printf("YES\n");
177 else
178 printf("NO\n");
179 }
180 return 0;
181 }