首先提醒一下不要读错题目,因为题目并没有要求旋转 $90$ 度是顺时针还是逆时针。

将 $dx,dy$ 分开考虑,题目转换为 $dx = A_1,dy = 0$,然后 $A_{2i + 1},A_{2i} (i > 0)$ 分别对 $dx,dy$ 产生影响,问能否凑成题目所求的数 $(x,y)$。尝试 $\texttt{dp}$,若某一维的 $x$ 可以得到,那么对于本轮的 $A$,可以得到 $x - A$ 与 $x + A$,转移的时候直接枚举上一轮所有被标记的位置即可。为了方便负数的操作,直接使用 map 存储。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
#define init(x) memset (x,0,sizeof (x))
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
using namespace std;
const int MAX = 1e3 + 5;
const int MOD = 1e9 + 7;
inline int read ();
int n,x,y,dx,dy,a[MAX];
map <int,int> dpx[MAX],dpy[MAX];
int main ()
{
//freopen (".in","r",stdin);
//freopen (".out","w",stdout);
n = read ();x = read ();y = read ();
for (int i = 1;i <= n;++i) a[i] = read ();
//坐标x y 分开考虑
dpx[1][a[1]] = 1;//初始化
for (int i = 3;i <= n;i += 2)
for (auto j : dpx[i - 2])//由上一轮得到的数进行转移
dpx[i][j.first + a[i]] = dpx[i][j.first - a[i]] = 1;
dpy[0][0] = 1;//初始化
for (int i = 2;i <= n;i += 2)
for (auto j : dpy[i - 2])
dpy[i][j.first + a[i]] = dpy[i][j.first - a[i]] = 1;
if (dpx[(n & 1) ? n : n - 1].count (x) && dpy[(n & 1) ? n - 1 : n].count (y)) puts ("Yes");
else puts ("No");
return 0;
}
inline int read ()
{
int s = 0;int f = 1;
char ch = getchar ();
while ((ch < '0' || ch > '9') && ch != EOF)
{
if (ch == '-') f = -1;
ch = getchar ();
}
while (ch >= '0' && ch <= '9')
{
s = s * 10 + ch - '0';
ch = getchar ();
}
return s * f;
}