题目大意:
对于给定的数组
a
a
a,请问是否存在一个与
a
a
a等长的数组使得
a
i
=
b
j
−
b
k
a_i=b_j-b_k
ai=bj−bk。
思路:
一眼看到了数量级哈,只有10 !。天老爷哟~。
接下来我们来进行简单的分析,首先对于
a
a
a中的
n
n
n个数,假定有三个数
a
1
=
b
1
−
b
2
a_1=b_1-b_2
a1=b1−b2,
a
2
=
b
2
−
b
3
a_2=b_2-b_3
a2=b2−b3,
a
3
=
b
3
−
b
1
a_3=b_3-b_1
a3=b3−b1
显然我们可以得到,
a
1
+
a
2
+
a
3
=
0
a_1+a_2+a_3=0
a1+a2+a3=0
那么也就是说,我们将
b
b
b数组看做一个有
n
n
n个点首尾相连的环,起初将相邻两点连上一条有向边,由上述的分析可知,对于b形成的环,其边权之和一定为0,但是我们仅仅知道边权分别为a的每一个值,我们并不知道他是由
b
i
−
b
j
b_i-b_j
bi−bj得来还是由
b
j
−
b
i
b_j-b_i
bj−bi得来,所以我们将b换做一个无向图,通过对边权值正负号的变化可以得出一组合理的解,使得b的权值和为
0
0
0。
至此我们的结论分析完毕。
那么我们可以知道,对于每一个 a i a_i ai我们都有三种操作加他,减他,不管他。因此时间复杂度为 O ( N ∗ 3 1 0 ) O(N*3^10) O(N∗310)利用dfs爆搜即可
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<sstream>
#include<queue>
#define fr for
#define pi 3.1415926535
#define me(a,b,c) memset(a,b,sizeof c)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
typedef pair<int, int> pii;
const int N = 1e4 + 10;
map<int, int>mp;
int n;
int a[300];
bool dfs(int num, int sum, bool st) {
if (num > n) {
return sum == 0 && st;
}
return dfs(num + 1, sum - a[num], true) || dfs(num + 1, sum + a[num], true) || dfs(num + 1, sum, st);
}
int main() {
int t;
cin >> t;
while (t--)
{
cin >> n;
fr(int i = 1; i <= n; i++)cin >> a[i];
if (dfs(1, 0, false)) {
puts("YES");
}
else puts("NO");
}
}
还有一种按位枚举的方法,是标程所给的。俺没有参透。。。但是确实学到了。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<sstream>
#include<queue>
#define fr for
#define pi 3.1415926535
#define me(a,b,c) memset(a,b,sizeof c)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
typedef pair<int, int> pii;
const int N = 1e4 + 10;
int T;
int n;
int a[N];
int main()
{
cin >> T;
while (T --)
{
cin >> n;
int res = 1;
for (int i = 1; i <= n; i ++) cin >> a[i], res *= 3;
int flag = 0;
for (int i = 1; i <= res - 1; i ++)
{
int t = i, sum = 0;
for (int i = 1; i <= n; i ++)
{
if (t % 3 == 1) sum += a[i];
if (t % 3 == 2) sum -= a[i];
t /= 3;
}
if (!sum)
{
flag = 1;
break;
}
}
if (flag) puts("YES");
else puts("NO");
}
}