1. 题目描述
给定几个三角形拼成一个百慕大三角形。
2. 基本思路
基本思路肯定是搜索,关键点是剪枝。
(1) 若存在长度为$l$的边,则一定可以拼成长度为$k \cdot l$的三角形,则可拼成长度为$k \cdot l$的百慕大三角形;
(2) 长度超过百慕大三角形的边长的三角形没有任何价值;
(3) 百慕大三角形中每个正三角形可以作为正多边形的顶点,倒三角形可以作为倒正三角形的顶点。
因此,可以将每个三角形映射到二维坐标,高度为$y$,倒三角形的$x$坐标为偶数,正三角形的$x$坐标为奇数。
对于每个有效的坐标,枚举可以使用的三角形。暴力深搜可解。
然后,观察可发现每个百慕大是由6个正三角形或3个平行四边形组成。因此,假设可以拼成三角形或平行四边形,那么一定可以拼成百慕大。
对于不同的形状,不需要重写dfs函数,只需要限定好边界即可。
3. 代码
1 /* 1362 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string> 5 #include <map> 6 #include <queue> 7 #include <set> 8 #include <stack> 9 #include <vector> 10 #include <deque> 11 #include <bitset> 12 #include <algorithm> 13 #include <cstdio> 14 #include <cmath> 15 #include <ctime> 16 #include <cstring> 17 #include <climits> 18 #include <cctype> 19 #include <cassert> 20 #include <functional> 21 #include <iterator> 22 #include <iomanip> 23 using namespace std; 24 //#pragma comment(linker,"/STACK:102400000,1024000") 25 26 #define sti set<int> 27 #define stpii set<pair<int, int> > 28 #define mpii map<int,int> 29 #define vi vector<int> 30 #define pii pair<int,int> 31 #define vpii vector<pair<int,int> > 32 #define rep(i, a, n) for (int i=a;i<n;++i) 33 #define per(i, a, n) for (int i=n-1;i>=a;--i) 34 #define clr clear 35 #define pb push_back 36 #define mp make_pair 37 #define fir first 38 #define sec second 39 #define all(x) (x).begin(),(x).end() 40 #define SZ(x) ((int)(x).size()) 41 #define lson l, mid, rt<<1 42 #define rson mid+1, r, rt<<1|1 43 44 const int maxn = 30; 45 const int maxm = 60; 46 int c[maxn], s[maxn]; 47 int a[maxn], R[maxm]; 48 bool visit[maxm][maxm]; 49 int n, m, bound; 50 bool flag; 51 52 void init() { 53 rep(i, 1, maxn) 54 c[i] = c[i-1] + i*2-1; 55 rep(i, 1, maxn) 56 s[i] = 6 * c[i]; 57 } 58 59 inline bool judge(int x, int y) { 60 return y<=0 || y>bound || x<=0 || x>R[y]; 61 } 62 63 bool check(int x, int y, int n) { 64 if (x & 1) { 65 // straight triangle 66 int yy = y; 67 rep(i, 1, n+1) { 68 int xx = x, l = i*2-1; 69 rep(j, 0, l) { 70 if (judge(xx, yy) || visit[yy][xx]) return false; 71 ++xx; 72 } 73 ++yy; 74 } 75 } else { 76 // reverse triangle 77 int yy = y; 78 int c = 0; 79 per(i, 1, n+1) { 80 int xx = x + c * 2, l = i*2-1; 81 rep(j, 0, l) { 82 if (judge(xx, yy) || visit[yy][xx]) return false; 83 ++xx; 84 } 85 ++c; 86 ++yy; 87 } 88 } 89 return true; 90 } 91 92 void update(int x, int y, int n, bool delta) { 93 if (x & 1) { 94 // straight triangle 95 int yy = y; 96 rep(i, 1, n+1) { 97 int xx = x, l = i*2-1; 98 rep(j, 0, l) { 99 visit[yy][xx] = delta; 100 ++xx; 101 } 102 ++yy; 103 } 104 } else { 105 // reverse triangle 106 int yy = y; 107 int c = 0; 108 per(i, 1, n+1) { 109 int xx = x + c * 2, l = i*2-1; 110 rep(j, 0, l) { 111 visit[yy][xx] = delta; 112 ++xx; 113 } 114 ++c; 115 ++yy; 116 } 117 } 118 } 119 120 void dfs(int r, int dep) { 121 if (dep > bound) { 122 flag = true; 123 return ; 124 } 125 126 int rr = r + 1, depp = dep; 127 if (r == R[dep]) { 128 rr = 1; 129 ++depp; 130 } 131 132 if (visit[dep][r]) { 133 dfs(rr, depp); 134 } else { 135 rep(i, 0, m) { 136 int l = a[i]; 137 if (check(r, dep, l)) { 138 update(r, dep, l, true); 139 dfs(rr, depp); 140 update(r, dep, l, false); 141 if (flag) return; 142 } else { 143 break; 144 } 145 } 146 } 147 } 148 149 bool judge1() { 150 flag = false; 151 bound = n; 152 memset(visit, false, sizeof(visit)); 153 rep(i, 1, n+1) 154 R[i] = 2*i-1; 155 dfs(1, 1); 156 return flag; 157 } 158 159 bool judge2() { 160 flag = false; 161 bound = n; 162 memset(visit, false, sizeof(visit)); 163 rep(i, 1, n+1) 164 R[i] = 2*i-1; 165 dfs(1, 1); 166 return flag; 167 } 168 169 bool judge3() { 170 flag = false; 171 bound = n*2; 172 memset(visit, false, sizeof(visit)); 173 rep(i, 1, n+1) { 174 R[i] = n*2 + 2*i-1; 175 } 176 rep(i, n+1, n*2+1) { 177 rep(j, 1, 2*(i-n)) 178 visit[i][j] = true; 179 R[i] = (n + n)*2; 180 } 181 dfs(1, 1); 182 return flag; 183 } 184 185 void solve() { 186 sort(a, a+m); 187 rep(i, 0, m) { 188 if (n%a[i] == 0) { 189 puts("YES"); 190 return ; 191 } 192 } 193 if (a[0] > n) { 194 puts("NO"); 195 return ; 196 } 197 198 { // filter unnecessary 199 int j = 1; 200 201 rep(i, 1, m) { 202 if (a[i] > n) 203 break; 204 bool flag = true; 205 rep(k, 0, j) { 206 if (a[i]%a[k] == 0) { 207 flag = false; 208 } 209 } 210 if (flag) 211 a[j++] = a[i]; 212 } 213 m = j; 214 } 215 216 if (judge1()) { 217 puts("YES"); 218 return ; 219 } 220 221 if (judge2()) { 222 puts("YES"); 223 return ; 224 } 225 226 if (judge3()) { 227 puts("YES"); 228 return ; 229 } 230 231 puts("NO"); 232 } 233 234 int main() { 235 cin.tie(0); 236 ios::sync_with_stdio(false); 237 #ifndef ONLINE_JUDGE 238 freopen("data.in", "r", stdin); 239 freopen("data.out", "w", stdout); 240 #endif 241 242 int t; 243 244 scanf("%d", &t); 245 while (t--) { 246 scanf("%d%d", &n,&m); 247 rep(i, 0, m) 248 scanf("%d", a+i); 249 solve(); 250 } 251 252 #ifndef ONLINE_JUDGE 253 printf("time = %ldms.\n", clock()); 254 #endif 255 256 return 0; 257 }
时间: 2024-10-09 13:17:12