【003】平方求和

  • 平方求和
    • 题目描述
    • 输入输出
    • 示例输入
    • 实例输出
    • DFS Depth First Search
    • cache优化
    • 剪枝
    • 深度剪枝
    • 预测剪枝
    • BFS Breath First Search

平方求和

题目描述

对于一个非负整数n,最少需要几个完全平方数,使其和为n?

输入输出

输入
- 第一行是n;如果n为-1,表示输入结束
输出
- 针对每组数据,输出最少需要的完全平方数

示例输入

3
4
5
-1

实例输出

3
1
2

#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#include 
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 
#include 
#include 
#include 
#include 
#include 
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

#include 
#include 
#include 
#include 
#include 
#include 
#include 
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

你可能感兴趣的:(刷题使我快乐)