[PAT] A1103 Integer Factorization

tech2022-09-05  110

(dfs深度优先搜索)

思路

先把i从0开始所有的i的p次方的值存储在v[i]中,直到v[i] > n为止。(如果在递归过程中计算次方,会做很多重复工作,很浪费时间。) 然后深度优先搜索,记录当前正在相加的index(即v[i]的i的值),当前的总和tempSum,当前K的总个数tempK,以及因为题目中要求输出因子的和最大的那个,所以保存一个facSum为当前因子的和,让它和maxFacSum比较,如果比maxFacSum大就更新maxFacSum和要求的ans数组的值。 在ans数组里面存储因子的序列,tempAns为当前深度优先遍历而来的序列,从v[i]的最后一个index开始一直到index == 1,因为这样才能保证ans和tempAns数组里面保存的是从大到小的因子的顺序。 一开始maxFacSum == -1,如果dfs后maxFacSum并没有被更新,还是-1,那么就输出Impossible,否则输出答案。 剪枝: 1.tempK==K但是tempSum!=n的时候需要剪枝 2.在枚举的时候,按顺序枚举,上界或者下界可进行剪枝 3.当且仅当tempSum + v[index] <= n时,进行下一层的DFS,而不要进入下一层DFS发现不满足条件再返回,这样开销会比较大 4.每次temv的push_back、pop_back都需要重新分配内存空间,比较耗时,由于答案的序列长度是确定的,可以将ans序列初始化为定长的,这样在递归的过程中就不需要push、pop; pow的计算结果可以保存下来,以免重复计算,耗用多余的时间

1.要先存好次方计算后的值,避免递归时重复计算。 2.直接利用maxsum来判断是否有解,通过设初值为负数。无需额外建立标记判断。 3.倒着递归,从大数开始判断。

AC代码

/*第二次写*/ #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<math.h> #include<vector> using namespace std; int n, k, p, maxsum = -1; vector<int>num, ans, bestans; void DFS(int index, int result, int sum, int x) { if (result == n && x == k) { if (sum > maxsum) { bestans = ans; maxsum = sum; } else if (sum == maxsum) { int i = k - 1; while (i >= 0 && ans[i] == bestans[i])i--; if (ans[i] > bestans[i])bestans = ans; } return; } else if (index < 0 || x >= k || result >= n)return; if (result + num[index] <= n) { ans[x] = index + 1; DFS(index, result + num[index], sum + index, x + 1); } DFS(index - 1, result, sum, x); } int main() { int i, a, b; scanf("%d%d%d", &n, &k, &p); ans.resize(k); bestans.resize(k); for (i = 1; i <= n; i++) { a = pow(i, p); if (a > n)break; num.push_back(a); } DFS(num.size() - 1, 0, 0, 0); if (maxsum < 0)printf("Impossible"); else { printf("%d = %d^%d", n, bestans[0], p); for (i = 1; i < k; i++)printf(" + %d^%d", bestans[i], p); } return 0; } #define _CRT_SECURE_NO_WARNINGS #include<cstdio> #include<iostream> #include<vector> #include<algorithm> #include<cmath> using namespace std; #define MAX 500 int n, k, p, maxsum = -1; vector<int>v; vector<int>solution, maxsolution; void optmax() { int i = 0; while (solution[i] == maxsolution[i])i++; if (solution[i] > maxsolution[i]) maxsolution = solution; } void DFS(int index, int count, int ans, int sum) { if (count == k && ans == n) { if (maxsum < sum) { maxsum = sum; maxsolution = solution; } else if (maxsum == sum) optmax(); //此处可以不用判断相等情况,也能AC。 return; } if (index == 0 || ans > n || count >= k)return; if (ans + v[index] <= n) { solution.push_back(index); DFS(index, count + 1, ans + v[index], sum + index); solution.pop_back(); } DFS(index - 1, count, ans, sum); } int main() { scanf("%d%d%d", &n, &k, &p); int temp = 0, index = 1; while (temp <= n) { v.push_back(temp); temp = pow(index, p); index++; } DFS(v.size() - 1, 0, 0, 0); if (maxsum < 0)printf("Impossible"); else { printf("%d = %d^%d", n, maxsolution[0], p); for (int i = 1; i < k; i++) printf(" + %d^%d", maxsolution[i], p); } return 0; }

如果改成正着来,测试点5就超时了...实在想不通是什么回事,希望走过路过的大神们帮我看看,感激不尽!!! (我想应该是从大数开始比较容易到达边界,减少了递归次数)

#define _CRT_SECURE_NO_WARNINGS #include<cstdio> #include<iostream> #include<vector> #include<map> #include<algorithm> #include<cmath> using namespace std; #define MAX 500 int n, k, p, maxsum = -1; vector<int>v; vector<int>solution, maxsolution; bool cmp(int a, int b) { return a > b; } void optmax() { int i = 0; while (solution[i] == maxsolution[i])i++; if (solution[i] > maxsolution[i]) maxsolution = solution; } void DFS(int index, int count, int ans, int sum) { if (count == k && ans == n) { if (maxsum < sum) { maxsum = sum; maxsolution = solution; } else if (maxsum == sum) optmax(); return; } if (index >= v.size() || ans > n || count >= k)return; if (ans + index <= n) { solution[count] = index; DFS(index, count + 1, ans + v[index], sum + index); } DFS(index + 1, count, ans, sum); } int main() { scanf("%d%d%d", &n, &k, &p); solution.resize(k); int temp = 0, index = 1; while (temp <= n) { v.push_back(temp); temp = pow(index, p); index++; } DFS(1, 0, 0, 0); if (maxsum < 0)printf("Impossible"); else { printf("%d = %d^%d", n, maxsolution[k - 1], p); for (int i = k - 2; i >= 0; i--) printf(" + %d^%d", maxsolution[i], p); } return 0; }
最新回复(0)