• hiho #1372:平方求 (bfs)


    #1372 : 平方求和

    时间限制:1000ms
    单点时限:1000ms
    内存限制:256MB

    描述

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

    输入

    输入包含多组数据。对于每组数据:

    第一行是n;如果n为-1,表示输入结束。(0 <= n <= 1000000001)  

    输出

    针对每组数据,输出最少需要的完全平方数。

    样例输入
    3
    4
    5
    -1
    样例输出
    3
    1
    2

    思路:

    拿到这个题,我第一想到的是贪心,每次减去一个最大数的平方,但是有时候这样会得不到正确的答案,比如19 ,贪心的话就是4,1,1,1.。。。正确的应该是3,3,1.。。。

    然后dp,dp虽然可以得到正确的答案,但是时间复杂度高了。pass。

    在想到搜索

    让我们可视化一下,

    原来是个搜索的题目。

    如何加速?

    我们应该深度优先搜索吗?

    当然不是啦!因为我们求的是最少的拆解,所以应该宽度优先搜索。

     宽搜的时候,用一个last和一个nlast分别记录当前行的最后一个元素,和下一行的最后一个元素。

    如何再加速?

    如果我们为了收敛快,似乎方向反了。

    如何再加速?

    我们有些节点是不是可能重复访问?建立一个hash表存一下吧。

    如何再快呢?

    证明题:每个正整数都可以表示为4个完全平方数的和。

    什么?居然还需要数论的知识。我不知道怎么办?

    没什么啊,我们刚才的宽度优先搜索已经能够保证和这个算法是一个复杂度了。

    代码:

    宽搜:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <queue>
     4 using namespace std;
     5 
     6 //5324124312
     7 int bfs(long long n)
     8 {
     9     queue<long long> q;
    10     int t = 1;
    11     long long head,last=n,nlast; //last当前行最右,nlast下一行最右
    12     q.push(n);
    13     while (!q.empty())
    14     {
    15         head = q.front();
    16         if (t == 3)
    17         {
    18             int c = 444;
    19         }
    20 
    21         if (t == 4)
    22             break;
    23         q.pop();
    24         if (head != 0)
    25         {
    26             for (int i = sqrt(head); i > 0; i--)
    27             {
    28                 if (head - i*i == 0)
    29                     return t;
    30                 q.push(head-i*i);
    31 
    32                 nlast = head - i*i;
    33             }        
    34 
    35             if (head == last && !q.empty())
    36             {
    37                 t++;
    38                 last = nlast;
    39             }
    40         }
    41     }
    42 }
    43 
    44 int main()
    45 {
    46     long long n;
    47     while (cin>>n)
    48     {
    49         if (n == -1)
    50             break;
    51         cout<< bfs(n)<<endl;
    52 
    53     }
    54     system("pause");
    55     return 0;
    56 }

     数论方法AC:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <queue>
     4 using namespace std;
     5 
     6 //5324124312
     7 bool is_sqrt(long long n)
     8 {
     9     int m = sqrt(n);
    10     if (m*m == n)
    11         return true;
    12     else
    13         return false;
    14 }
    15 
    16 int solve(long long n)
    17 {
    18     if (is_sqrt(n))
    19         return 1;
    20     while (n % 4 == 0)
    21         n /= 4;
    22 
    23     if (n % 8 == 7)
    24         return 4;
    25 
    26     for (int i = 0; i*i < n; i++)
    27     {
    28         if (is_sqrt(n - i*i))
    29             return 2;
    30     }
    31     return 3;
    32 }
    33 
    34 int main()
    35 {
    36     long long n;
    37     while (cin>>n)
    38     {
    39         if (n == -1)
    40             break;
    41         cout<< solve(n)<<endl;
    42 
    43     }
    44     system("pause");
    45     return 0;
    46 }
  • 相关阅读:
    .NET 统一用户管理 -- 统一鉴权
    .NET 统一用户管理 -- 单点登录
    基于.net 职责链来实现 插件模式
    电商开放平台设计
    docker搭建一个渗透测试环境 bwapp为例
    dcoker运行msf
    关于构造靶场
    判断网站是不是真实ip
    H3C设备配置ARP攻击防御
    Java代码审计 HTTP头操纵 response.addHeader()
  • 原文地址:https://www.cnblogs.com/SeekHit/p/5939280.html
Copyright © 2020-2023  润新知