dfs解E题
1.对题目进行分析 可知数组中的每个数都满足大于1 而且在操作过程中a[i]大于等于2 所以不存在有0 的情况.
2.因为可以进行任意次操作 所以任意一组数据我们都可以 将他变为 n-1项都是1 最后一项为sum-(n-1) 根据此推导 我们可以证明答案只有两种情况 也就是n-1和n的情况
3.了解了第2点 我们就可以开始着手写代码了 我们只需要判断 sum是否能由n个有趣数组成 由于数据量小 我们可以采取搜索的模式 在限定的数据内有趣数不超过100 所以dfs能在1s内跑完 证毕
以下请见代码
/*¥¥¥¥CodePoet¥¥¥¥*/
#include<bits/stdc++.h>
using namespace std;
//判断该数是否有趣
bool check(int x)
{
int s = 0, y;
while (x) {
y = x % 10;
s += y;
x /= 10;
}
int t= sqrt(s);
if (t * t == s)
return true;
return false;
}
vector<int> a;
int n;
//定义标识符
int flag = 0;
void dfs(int x, int cnt, int now)
{
//如果能分配成n个数 就不用继续向下搜
if (cnt == n) {
//刚好分完说明最多为n个
if (x == 0) {
//设计标识符剪枝
flag = 1;
}
return;
}
//用now 使得分成的数单调 不会搜重复
for (int i = now;i < a.size();i++) {
//如果x可以分配出a[i]这么大就搜
if (x >= a[i] && flag == 0)
dfs(x - a[i], cnt + 1, i);
//如果已经搜出答案也就是flag==1 那么提前结束搜索
else break;
}
}
signed main()
{
//ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//预处理好有趣数数组 数据不会超过20000
for (int i = 1;i * i <= 20000;i++) {
if (check(i * i)) {
a.push_back(i * i);
// cout << a[a.size() - 1] << ' ';
}
}
int T;
cin >> T;
while (T--) {
//初始化标识符
flag = 0;
cin >> n;
vector<int> v(n + 1);
int sum = 0;
//统计和
for (int i = 1;i <= n;i++) {
cin >> v[i];
sum += v[i];
}
//开搜
dfs(sum, 0, 0);
if (flag == 1)
cout << n << '\n';
else
cout << n - 1 << '\n';
}
}
以上就是我对思路 有任何疑问可以私信我 感谢观看