平方求和
题目描述
对于一个非负整数n,最少需要几个完全平方数,使其和为n?
输入输出
输入
- 第一行是n;如果n为-1,表示输入结束
输出
- 针对每组数据,输出最少需要的完全平方数
示例输入
3
4
5
-1
实例输出
3
1
2
DFS (Depth First Search)
#include <iostream>
#include <cstdio>
#include <fstream>
#include <ctime>
using namespace std;
class SqureSum {
public:
int search(int n) {
if (n == 0) return n;
int result = n;
for (int i=1; i*i<=n; ++i) {
int temp = search(n - i*i);
if (temp + 1 < result) result = temp + 1;
}
return result;
}
};
int main() {
SqureSum ss;
ifstream is("../input.txt");
int n;
is >> n;
while (n != -1) {
clock_t start = clock();
printf("%d Result %d ", n, ss.search(n));
clock_t end = clock();
printf("Time: %fms\n", (float)(end - start)/CLOCKS_PER_SEC*1000);
is >> n;
}
return 0;
}
输出
3 Result 3 Time: 0.000000ms
4 Result 1 Time: 0.000000ms
5 Result 2 Time: 0.000000ms
6 Result 3 Time: 0.000000ms
7 Result 4 Time: 0.000000ms
8 Result 2 Time: 0.000000ms
9 Result 1 Time: 0.000000ms
10 Result 2 Time: 0.000000ms
21 Result 3 Time: 0.000000ms
31 Result 4 Time: 1.000000ms
41 Result 2 Time: 19.000000ms
51 Result 3 Time: 573.000000ms
61 Result 2 Time: 17303.000000ms
cache优化
#include <iostream>
#include <cstdio>
#include <fstream>
#include <ctime>
#include <map>
using namespace std;
class SqureSum {
private:
map<int, int> cache;
public:
int search(int n) {
if (n == 0) return n;
if (cache.find(n) != cache.end()) return cache[n];
int result = n;
for (int i=1; i*i<=n; ++i) {
int temp = search(n - i*i);
if (temp + 1 < result) result = temp + 1;
}
cache[n] = result;
return result;
}
};
int main() {
SqureSum ss;
ifstream is("../input.txt");
int n;
is >> n;
while (n != -1) {
clock_t start = clock();
printf("%d Result %d ", n, ss.search(n));
clock_t end = clock();
printf("Time: %fms\n", (float)(end - start)/CLOCKS_PER_SEC*1000);
is >> n;
}
return 0;
}
输出
3 Result 3 Time: 0.000000ms
4 Result 1 Time: 0.000000ms
5 Result 2 Time: 0.000000ms
6 Result 3 Time: 0.000000ms
7 Result 4 Time: 0.000000ms
8 Result 2 Time: 0.000000ms
9 Result 1 Time: 0.000000ms
10 Result 2 Time: 0.000000ms
21 Result 3 Time: 0.000000ms
31 Result 4 Time: 0.000000ms
41 Result 2 Time: 0.000000ms
51 Result 3 Time: 0.000000ms
61 Result 2 Time: 0.000000ms
101 Result 2 Time: 0.000000ms
1001 Result 3 Time: 14.000000ms
10001 Result 2 Time: 560.000000ms
剪枝
#include <iostream>
#include <cstdio>
#include <fstream>
#include <ctime>
#include <map>
#include <cmath>
using namespace std;
class SqureSum {
private:
map<int, int> cache;
public:
int search(int n) {
if (n == 0) return n;
if (cache.find(n) != cache.end()) return cache[n];
int result = n;
int ceil = (int)(sqrt(n));
if (ceil * ceil == n) {
cache[n] = 1;
return 1;
}
for (int i=ceil; i>0; --i) {
int temp = search(n - i*i);
if (temp + 1 < result) result = temp + 1;
}
cache[n] = result;
return result;
}
};
int main() {
SqureSum ss;
ifstream is("../input.txt");
int n;
is >> n;
while (n != -1) {
clock_t start = clock();
printf("%d Result %d ", n, ss.search(n));
clock_t end = clock();
printf("Time: %fms\n", (float)(end - start)/CLOCKS_PER_SEC*1000);
is >> n;
}
return 0;
}
输出
3 Result 3 Time: 0.000000ms
4 Result 1 Time: 0.000000ms
5 Result 2 Time: 0.000000ms
6 Result 3 Time: 0.000000ms
7 Result 4 Time: 0.000000ms
8 Result 2 Time: 0.000000ms
9 Result 1 Time: 0.000000ms
10 Result 2 Time: 0.000000ms
21 Result 3 Time: 0.000000ms
31 Result 4 Time: 0.000000ms
41 Result 2 Time: 0.000000ms
51 Result 3 Time: 0.000000ms
61 Result 2 Time: 0.000000ms
101 Result 2 Time: 0.000000ms
1001 Result 3 Time: 15.000000ms
10001 Result 2 Time: 540.000000ms
100001 Result 3 Time: 21555.000000ms
深度剪枝
#include <iostream>
#include <cstdio>
#include <fstream>
#include <ctime>
#include <map>
#include <cmath>
using namespace std;
class SqureSum {
private:
map<int, int> cache;
int best = 999;
public:
int search(int n, int depth) {
if (n == 0) return n;
if (cache.find(n) != cache.end()) return cache[n];
if (depth > best) return n;
int result = n;
int ceil = (int)(sqrt(n));
if (ceil * ceil == n) {
cache[n] = 1;
if (best > depth) best = depth;
return 1;
}
for (int i=ceil; i>0; --i) {
int temp = search(n - i*i, depth + 1);
if (temp + 1 < result) result = temp + 1;
if (best > temp+depth) best = temp + depth;
if (temp == 1) break;
}
cache[n] = result;
return result;
}
};
int main() {
SqureSum ss;
ifstream is("../input.txt");
int n;
is >> n;
while (n != -1) {
clock_t start = clock();
printf("%d Result %d ", n, ss.search(n, 0));
clock_t end = clock();
printf("Time: %fms\n", (float)(end - start)/CLOCKS_PER_SEC*1000);
is >> n;
}
return 0;
}
输出
3 Result 3 Time: 0.000000ms
4 Result 1 Time: 0.000000ms
5 Result 2 Time: 0.000000ms
6 Result 3 Time: 0.000000ms
7 Result 4 Time: 0.000000ms
8 Result 2 Time: 0.000000ms
9 Result 1 Time: 0.000000ms
10 Result 2 Time: 0.000000ms
21 Result 3 Time: 0.000000ms
31 Result 4 Time: 0.000000ms
41 Result 3 Time: 0.000000ms
51 Result 3 Time: 0.000000ms
61 Result 13 Time: 0.000000ms
101 Result 2 Time: 0.000000ms
1001 Result 3 Time: 0.000000ms
10001 Result 2 Time: 0.000000ms
100001 Result 3 Time: 1.000000ms
1000001 Result 2 Time: 0.000000ms
10000001 Result 3 Time: 0.000000ms
100000001 Result 2 Time: 0.000000ms
预测剪枝
#include <iostream>
#include <cstdio>
#include <fstream>
#include <ctime>
#include <map>
#include <cmath>
using namespace std;
class SqureSum {
private:
map<int, int> cache;
int best = 999;
public:
int search(int n, int depth) {
if (n == 0) return n;
if (cache.find(n) != cache.end()) return cache[n];
if (depth > best) return n;
int result = n;
int ceil = (int)(sqrt(n));
if (ceil * ceil == n) {
cache[n] = 1;
if (best > depth) best = depth;
return 1;
}
if (depth + 1 < best) {
for (int i = ceil; i > 0; --i) {
int temp = search(n - i * i, depth + 1);
if (temp + 1 < result) result = temp + 1;
if (best > temp + depth) best = temp + depth;
if (temp == 1) break;
}
}
cache[n] = result;
return result;
}
};
int main() {
SqureSum ss;
ifstream is("../input.txt");
int n;
is >> n;
while (n != -1) {
clock_t start = clock();
printf("%d Result %d ", n, ss.search(n, 0));
clock_t end = clock();
printf("Time: %fms\n", (float)(end - start)/CLOCKS_PER_SEC*1000);
is >> n;
}
return 0;
}
输出
3 Result 3 Time: 1.000000ms
4 Result 1 Time: 0.000000ms
5 Result 5 Time: 0.000000ms
6 Result 6 Time: 0.000000ms
7 Result 7 Time: 0.000000ms
8 Result 8 Time: 0.000000ms
9 Result 1 Time: 0.000000ms
10 Result 10 Time: 0.000000ms
21 Result 21 Time: 0.000000ms
31 Result 31 Time: 0.000000ms
41 Result 41 Time: 0.000000ms
51 Result 51 Time: 0.000000ms
61 Result 61 Time: 0.000000ms
101 Result 101 Time: 0.000000ms
1001 Result 1001 Time: 0.000000ms
10001 Result 10001 Time: 0.000000ms
100001 Result 100001 Time: 0.000000ms
1000001 Result 1000001 Time: 0.000000ms
10000001 Result 10000001 Time: 0.000000ms
100000001 Result 100000001 Time: 0.000000ms
BFS (Breath First Search)
#include <iostream>
#include <cstdio>
#include <fstream>
#include <ctime>
#include <map>
#include <cmath>
#include <queue>
using namespace std;
class SqureSum {
private:
map<int, int> cache;
int best = 999;
public:
int search(int n, int depth) {
if (n == 0) return n;
if (cache.find(n) != cache.end()) return cache[n];
if (depth > best) return n;
int result = n;
int ceil = (int)(sqrt(n));
if (ceil * ceil == n) {
cache[n] = 1;
if (best > depth) best = depth;
return 1;
}
if (depth + 1 < best) {
for (int i = ceil; i > 0; --i) {
int temp = search(n - i * i, depth + 1);
if (temp + 1 < result) result = temp + 1;
if (best > temp + depth) best = temp + depth;
if (temp == 1) break;
}
}
cache[n] = result;
return result;
}
int bfs(int n) {
queue<int> q;
q.push(n);
q.push(-1);
int need = 1;
while (!q.empty()) {
int tmp = q.front();
q.pop();
if (tmp < 0) {
q.push(tmp-1);
++need;
} else {
int ceil = (int)sqrt(tmp);
if (ceil * ceil == tmp) break;
for (int i=ceil; i>0; --i) {
q.push(tmp - i*i);
}
}
}
return need;
}
};
int main() {
SqureSum ss;
ifstream is("../input.txt");
int n;
is >> n;
while (n != -1) {
clock_t start = clock();
// printf("%d Result %d ", n, ss.search(n, 0));
printf("%d Result %d ", n, ss.bfs(n));
clock_t end = clock();
printf("Time: %fms\n", (float)(end - start)/CLOCKS_PER_SEC*1000);
is >> n;
}
return 0;
}
输出
3 Result 3 Time: 0.000000ms
4 Result 1 Time: 0.000000ms
5 Result 2 Time: 0.000000ms
6 Result 3 Time: 0.000000ms
7 Result 4 Time: 0.000000ms
8 Result 2 Time: 0.000000ms
9 Result 1 Time: 0.000000ms
10 Result 2 Time: 0.000000ms
21 Result 3 Time: 0.000000ms
31 Result 4 Time: 0.000000ms
41 Result 2 Time: 0.000000ms
51 Result 3 Time: 0.000000ms
61 Result 2 Time: 0.000000ms
101 Result 2 Time: 0.000000ms
1001 Result 3 Time: 0.000000ms
10001 Result 2 Time: 0.000000ms
100001 Result 3 Time: 4.000000ms
1000001 Result 2 Time: 0.000000ms
10000001 Result 3 Time: 256.000000ms
100000001 Result 2 Time: 0.000000ms