动态规划

1、剪绳子

给你一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1,m>1), 每段绳子的长度记为 k[0], k[1], k[2], …, k[m]。 请问 k[0] * k[1] * k[2] * … * k[m] 可能的最大乘积是多少? 例如,当绳子的长度为8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

解法一:动态规划

func max(a int,b int) int{
   if a>=b {
      return a
   }else {
      return b
   }
}

func main(){
   var N int
   fmt.Scan(&N)
   f := make([]int,N+1)
   for i:=1;i<=3;i++ {
      f[i]=i
   }
   for n:=2;n<=N;n++ {
      for i:=1;i<n;i++{
         f[n]=max(f[n],f[n-i]*f[i])
      }
   }
   fmt.Println(f[N])
}

解法二:贪心算法

func main(){
	var N,res int
	fmt.Scan(&N)
	m := float64(N/3)
	c := N%3
	if c == 1 {
		m-=1
		res = int(math.Pow(3,m)*4)
	}else if c==2 {
		res = int(math.Pow(3,m)*2)
	}else {
		res = int(math.Pow(3,m))
	}
	fmt.Println(res)
}

2、剪绳子加强版

给你一根长度为n的绳子,要求剪成m段,(上面剪成几段都可以,这里m给出)(m、n都是整数,n>1,m>1), 每段绳子的长度记为 k[0], k[1], k[2], …, k[m]。 请问 k[0] * k[1] * k[2] * … * k[m] 可能的最大乘积是多少? 例如,当绳子的长度为8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

func max(a int,b int) int{
	if a>=b {
		return a
	}else {
		return b
	}
}

func main(){
	var N,M int
	fmt.Scan(&N,&M)
	var f [][]int
	for i:=0;i<=N;i++ {
		temp := make([]int,M+1)
		f = append(f,temp)
	}
	for i:=1;i<=N-M+1;i++ {
		f[i][1]=i
	}
	fmt.Println(f)
	for j:=2;j<=M;j++{       //截成j段
		for i:=j;i-j<=N-M;i++{//木棍长度
			f[i][j]=f[i-1][j-1]
			for k:=1;i-k>=j;k++ {
				f[i][j] = max(f[i-k][j-1]*k,f[i][j])
			}
		}
	}
	fmt.Println(f[N][M])
}

3、【题目描述】魔法石矿(Mine.cpp/c/pas)
每个矿里有一定数量的魔法石,同时每个矿中都有一张说明书,说明在挖完此矿的魔法石后还可继续挖哪些矿,挖矿规则为可以从任何一个矿开始,到任何一个矿结束,同时挖完这个矿中的魔法石之后,可以选择它可继续挖的矿之一继续挖,但只能选择一条。如挖完1矿后,可挖2矿,再挖5矿,6矿,……但只可以向右挖,不能回头向左挖。请问如何挖才能挖出最多的魔法石?
【输入格式】
第一行为一个整数n,表示有n(n≤1000)个矿。第二行为n个整数,表示这n个矿的魔法石数。随后n行表示每个矿挖完后还能再挖哪些矿。
【输出格式
最多挖出的魔法石数。
【输入样例】
3
1 1 1
1 2 3
2 3
3
【输出样例】

3

方法一:

type Node struct {
	Max  		int  //以该矿结束可以取的最大值
	PreLink 	int   //上一个矿
	Lis 		[]int //link存每个矿挖完后还能再挖那些矿。
	W           int   //每个矿的值
}


func isNumber(c byte) bool {
	if c >= '0' && c <= '9' {
		return true
	} else {
		return false
	}
}

func main(){
	var N,i,j int
	var node []Node
	tempNode := Node{}
	fmt.Scan(&N)


	for i=0;i<N;i++ {
		fmt.Scan(&tempNode.W)
		tempNode.Max = tempNode.W
		tempNode.PreLink = i
		node = append(node,tempNode)
	}



    var c byte
	for i=0;i<N;i++ {
		for {
			fmt.Scanf("%c", &c)
			if isNumber(c) {
				l := int(c-'0')-1
				node[i].Lis = append(node[i].Lis, l)
			}
			if c == '\n' {
				break
			}
		}
	}

	for i=0;i<N;i++ {
		fmt.Println(node[i])
	}

	for i=0;i<N;i++ {
		for j=1;j<len(node[i].Lis);j++ {
			linkT := node[i].Lis[j]
			if node[linkT].Max < node[i].Max + node[linkT].W {
				node[linkT].Max = node[i].Max + node[linkT].W
				node[linkT].PreLink = i
			}
		}
	}

	max := 0
	linkM := 0
	for i=0;i<N;i++ {
		if node[i].Max > max {
			max = node[i].Max
			linkM = i
		}
	}
	fmt.Println("MAX:",max)

	for node[linkM].PreLink != linkM {
		fmt.Print(linkM,"<-")
		linkM = node[linkM].PreLink
	}
	fmt.Print(linkM)
}

方法二:

/*	for i=0;i<N;i++ {
		for j=len(node[i].Lis)-2;j>=0;j-- {
			linkT := node[i].Lis[j]
			if node[i].Max < node[linkT].Max + node[i].W {
				node[i].Max = node[linkT].Max + node[i].W
				node[i].PreLink = linkT
			}
		}
	}*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值