题意:给定一个序列 \(a_1,a_2,...,a_n\) ,问是否存在一个序列 \(b_1, b_2, ..., b_n\) ,使得对任意 \(a_i\) ,都有 \(b_j - b_k = a_i \ (1 \leq j、k \leq n)\) 。
分析:对于任意一个 \(a_i\) ,都存在一个关系,把 \(b_i\) 看作点权, \(a_i\) 看作边权,如果 \(b_j - b_k = a_i\) ,则从 \(j\) 向 \(k\) 连一条边。则问题变成了一张 \(G(n, n)\) 图,那么图中一定存在一个环(弱连通图上),由于关系是相减的,如果存在序列 \(b\) ,那么环上所有边权之和在同方向下一定为 \(0\) (枚举方向,也就是正负号,枚举箭头方向保持一致),只要存在这么一条环即可。
Code
// cur表示枚举到了哪个点,sum表示环上贡献总和,is_loop表示目前是否形成环
bool check (int cur, int sum, int is_loop) // 可能存在空环
{
if (cur > n)
return sum == 0 && is_loop; // 贡献总和为0且形成了环
bool res = false;
res |= check(cur+1, sum, is_loop); // 环上不包含这个点
res |= check(cur+1, sum + a[cur], 1); // 环上包含,且该值在环上的贡献为正数
res |= check(cur+1, sum - a[cur], 1); // 环上包含,且该值在环上的贡献为正数
return res;
}
void solve ()
{
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
puts(check(1, 0, 0) ? "YES" : "NO");
}