【003】平方求和

平方求和

题目描述

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

输入输出

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

示例输入

3
4
5
-1

实例输出

3
1
2

#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

#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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值