hiho #1372:平方求 (bfs)
#1372 : 平方求和
描述
对于一个非负整数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个完全平方数的和。
什么?居然还需要数论的知识。我不知道怎么办?
没什么啊,我们刚才的宽度优先搜索已经能够保证和这个算法是一个复杂度了。
代码:
宽搜:
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std; //
int bfs(long long n)
{
queue<long long> q;
int t = ;
long long head,last=n,nlast; //last当前行最右,nlast下一行最右
q.push(n);
while (!q.empty())
{
head = q.front();
if (t == )
{
int c = ;
} if (t == )
break;
q.pop();
if (head != )
{
for (int i = sqrt(head); i > ; i--)
{
if (head - i*i == )
return t;
q.push(head-i*i); nlast = head - i*i;
} if (head == last && !q.empty())
{
t++;
last = nlast;
}
}
}
} int main()
{
long long n;
while (cin>>n)
{
if (n == -)
break;
cout<< bfs(n)<<endl; }
system("pause");
return ;
}
数论方法AC:
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std; //
bool is_sqrt(long long n)
{
int m = sqrt(n);
if (m*m == n)
return true;
else
return false;
} int solve(long long n)
{
if (is_sqrt(n))
return ;
while (n % == )
n /= ; if (n % == )
return ; for (int i = ; i*i < n; i++)
{
if (is_sqrt(n - i*i))
return ;
}
return ;
} int main()
{
long long n;
while (cin>>n)
{
if (n == -)
break;
cout<< solve(n)<<endl; }
system("pause");
return ;
}
hiho #1372:平方求 (bfs)的更多相关文章
- PKU 2002 Squares(二维点哈希+平方求余法+链地址法)
题目大意:原题链接 给定平面上的N个点,求出这些点一共可以构成多少个正方形. 解题思路: 若正方形为ABCD,A坐标为(x1, y1),B坐标为(x2, y2),则很容易可以推出C和D的坐标.对于特定 ...
- hiho #1305 区间求差
#1305 : 区间求差 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定两个区间集合 A 和 B,其中集合 A 包含 N 个区间[ A1, A2 ], [ A3, ...
- (step4.2.1) hdu 1372(Knight Moves——BFS)
解题思路:BFS 1)马的跳跃方向 在国际象棋的棋盘上,一匹马共有8个可能的跳跃方向,如图1所示,按顺时针分别记为1~8,设置一组坐标增量来描述这8个方向: 2)基本过程 设当前点(i,j),方向k, ...
- HDU 1372 Knight Moves(BFS)
题目链接 Problem Description A friend of you is doing research on the Traveling Knight Problem (TKP) whe ...
- hiho 1613 - 墨水滴 - bfs+优先队列 *
题目链接 小Ho有一张白纸,上面有NxN个格子.小Ho可以选择一个格子(X, Y),在上面滴一滴墨水.如果这滴墨水的颜色深度是G,那么这个格子也会被染成深度为G的格子.同时周围的格子也会被这滴墨水浸染 ...
- HDU5957 Query on a graph(拓扑找环,BFS序,线段树更新,分类讨论)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5957 题意:D(u,v)是节点u和节点v之间的距离,S(u,v)是一系列满足D(u,x)<=k的点 ...
- HAOI2018游记
前言 很懒. 太懒了. 不仅懒得写题..连游记都懒得写.. 花点时间填一下坑吧..不过话说我去年的NOI/APIO/CTSC游记也没写.. 省选前 板子好像一早就打完了,没什么可干的. 也不愿意开新题 ...
- K - 迷宫问题
/*定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, ...
- python机器学习《回归 一》
唠嗑唠嗑 依旧是每一次随便讲两句生活小事.表示最近有点懒,可能是快要考试的原因,外加这两天都有笔试和各种面试,让心情变得没那么安静的敲代码,没那么安静的学习算法.搞得第一次和技术总监聊天的时候都不太懂 ...
随机推荐
- 整数分解 && 质因数分解
输入整数(0-30)分解成所有整数之和.每四行换行一次. 一种方法是通过深度优先枚举出解.通过递归的方式来实现. #include <stdio.h> #include <strin ...
- win7开防火墙,允许别人远程
- 自然语言15_Part of Speech Tagging with NLTK
https://www.pythonprogramming.net/part-of-speech-tagging-nltk-tutorial/?completed=/stemming-nltk-tut ...
- Linux常用服务部署与优化之NFS篇
NFS(network file system)的简称,是linux系统之间常用的一种文件共享方式,下面简述其搭建过程,需要两个linux系统的虚拟机,假设客户端的ip为192.168.1.105,服 ...
- JSP简单标签开发
一.继承自SimpleTag接口的自定义标签实现类称为简单标签,接口中5个方法 1.setJspContext方法 用于把JSP页面的PageContext对象传递给标签处理器对象 2.setPare ...
- QT 初阶 第二章 创建对话框(查找对话框实例)
最终效果图: 该对话框由三个文件组成:finddialog.h .finddialog.cpp. main.cpp 代码+注释 /*--finddialog.h--*/ #ifndef FINDDIA ...
- js 滚动加载iframe框中内容
var isIE6 = !!window.ActiveXObject&&!window.XMLHttpRequest; //滚动加载 var scrollLoad =function( ...
- Javascript的匿名函数与自执行
1.匿名函数 函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没有函数名的函数. 1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式 第一种: ...
- 菜单each+hover
<script type="text/javascript"> $(document).ready(function(){ var src1= new Array('i ...
- ServiceBase 备份
using CanDoo.Contracts; using CanDoo.Core.Data; using System; using System.Collections.Generic; usin ...