求组成n的完全平方数的最少数字的组合

package main

import (
	"fmt"
   "math"
   "os"
   "bufio"
   "strconv"
)

func main() {
   getInput()
   // sqt(3)
}

func getInput(){
   reader:=bufio.NewReader(os.Stdin)

   for{
      fmt.Println("请输入一个正整数,退出请输入'quit':")

      line,_,ok:=reader.ReadLine()
      if ok!=nil{
         fmt.Println("输入错误")
         continue
      }
      cmd:=string(line)
      if "quit"==cmd{
         break
      }
      number,ok:=strconv.Atoi(cmd)
      if ok!=nil{
         fmt.Println("输入数字错误")
         continue
      }
      sqt(number)
   }
}


func sqt(x int) {
   res:=make([]int,0)
   if x > 0{
      res = getLastResult(x)
   } else {
      res = append(res, 0)
   }
   printResult(x, res)
}

func getLastResult(x int)[]int{
   //获取可能的最优解
   r:=getResult(x)
   l:=len(r)
   if l > 2{
      //l<=2,本身为完全平方数或者是最大完全平方数的两倍,肯定为最优解
      arr:=getSqtList(x)
      //第一个数为最大平方根的情况下,不存在其他更优解的可能,从第二个平方根开始迭代
      //[0,1]
      l2:=len(arr)
      j:=l2 - 2
      i:=3//保存最后一次的结果
      y:=0
      c:=make([]int,0)
      for {
         if y == x{
            //已完成
            break
         }
         if y + arr[j] <= x{
            //小于等于x,则第j个数满足要求
            //记录第j个数
            c = append(c, arr[j])
            //将第j个数加到y上
            y += arr[j]
         } else {
            //继续尝试j-1的数字
            j = j - 1
         }
         if len(c) > l{
            //已经超出最优解的可能
            //继续下一个
            j = l2 - i
            i ++
            //清空结果
            c=make([]int,0)
            y=0
            if j < 0{
               //已经没有可能性了
               break
            }
         }
      }
      if len(c) > 1 && len(c) < l{
         r = c
      }
   }
   return r
}

/*
从最大平方根开始
12=9+1+1+1 4
12=4+4+4   3
18=16+1+1
18=9+9
*/
func getResult(x int) []int{
   r:=make([]int,0)//记录结果
   for {
      if x == 0{
         break
      }
      j:=math.Floor(math.Sqrt(float64(x)))
      i:=math.Pow(j, 2)
      r = append(r, int(i))
      x -= int(i)
   }
   return r
}

func printResult(x int, a []int)  {
   s:=""
   for i:=0;i<len(a);i++{
      //要是有三元表达式,这可以省多少代码
      var f string
      if i==0{
         f=""
      } else {
         f="+"
      }
      s+=fmt.Sprintf("%s%d", f, a[i])
   }
   fmt.Println("number ", x, "=", s,",total=",len(a))
}

/*
从1开始,枚举小于n的所有完全平方数
*/
func getSqtList(x int) []int{
   a:=make([]int,0)
   i:=0
   for {
      j:=i*i
      if j>x{
         break
      }
      a=append(a,j)
      i++
   }
   return a
}

上一段代码测试后,发现不能处理99,这样的数字

改为穷举

package main

import (
	"fmt"
   "os"
   "bufio"
   "strconv"
)

func main() {
   getInput()
   // printResult(99,fx(99))
   // sqt(3)
}

//暴力穷举所有可能
func fx(x int) []int{
   list:=getSqtList(x)
   length:=len(list)
   res:=make([][]int,0)
   for i:=0;i<length;i++{
      j := length-i-1
      y := 0
      c:=make([]int, 0)
      for {
         if y == x{
            break
         }
         if y + list[j] <= x{
            y += list[j]
            c = append(c, list[j])
         } else {
            j --
         }
      }
      res = append(res, c)
   }
   req:=make([]int,0)
   for k,v := range res{
      if k==0 || len(req)>len(v){
         req=v
      }
   }
   return req
}

func getInput(){
   reader:=bufio.NewReader(os.Stdin)

   for{
      fmt.Println("请输入一个正整数,退出请输入'quit':")

      line,_,ok:=reader.ReadLine()
      if ok!=nil{
         fmt.Println("输入错误")
         continue
      }
      cmd:=string(line)
      if "quit"==cmd{
         break
      }
      number,ok:=strconv.Atoi(cmd)
      if ok!=nil{
         fmt.Println("输入数字错误")
         continue
      }
      sqt(number)
   }
}


func sqt(x int) {
   res:=make([]int,0)
   if x > 0{
      res = fx(x)
   } else {
      res = append(res, 0)
   }
   printResult(x, res)
}

func printResult(x int, a []int)  {
   s:=""
   for i:=0;i<len(a);i++{
      //要是有三元表达式,这可以省多少代码
      var f string
      if i==0{
         f=""
      } else {
         f="+"
      }
      s+=fmt.Sprintf("%s%d", f, a[i])
   }
   fmt.Println("number ", x, "=", s,",total=",len(a))
}

/*
从1开始,枚举小于n的所有完全平方数
*/
func getSqtList(x int) []int{
   a:=make([]int,0)
   i:=1
   for {
      j:=i*i
      if j>x{
         break
      }
      a=append(a,j)
      i++
   }
   return a
}

 

转载于:https://my.oschina.net/qii/blog/743648

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值