【诺坎普的酋长的学习历程】算法与数据结构【一】

        之前学习java,安卓一直想把自己的学习历程写成博客,但是之前确实是太懒惰,一直没写,现在开始学习算法和数据结构就不定期写写学到的东西,写的也很乱,就当作学习笔记,给自己看,或者如果能帮助到大家也是很好的,如果大家发现里面有什么错误,希望指出(毕竟本人是新手,刚刚迈入编程的大门三个月)

        注意!!!本文非教程,仅仅是自己的学习笔记,可参考(但我怀疑里面会有些错误,希望大家指出)。


        开更!

                                                                                                         第一节 算法之简单的动态规划

        动态规划是一种在多学科中普遍被使用的算法,它把一个复杂的问题分为若干重叠子问题,从而达到简化运算的效果,可以大大减少运行时间。动态规划的四个特点分别是1:具有最优子结构,这条是说当子问题最优的时候,父问题一定可以选择出一个最优解,具有这样的结构叫做最优子结构。2:子问题重叠,即父问题和子问题的实质是一样的,或者说问法和求解办法以及结果都是一类的问题叫做子问题重叠。3:具有边界,如果没有边界,子问题将会“无穷匮也”,那么我们就无法完成要求。4:子问题要相互独立,这就是说没有继承关系的子问题之间互不干扰,彼此独立,任何一个子问题的最优解都不影响父问题选择其他子问题的最优解。

        这里用经典的01背包问题来举例。

        假设你有一个容积为sm的背包,有n件物品,每件物品具有自己的价值和重量,现在想请你找出怎样装包可以让一个包内的物品品价值最大。

        为什么这个题目可以用动态规划的方法去解,首先,它具有最优子结构,当你选定最后一个物品的放进与否为一个父问题时,子问题总能找出一个最优情况,然后你只需要比较最后是装总价值大还是不装总价值大,其次,父问题和子问题是重叠的,每一个自问题都可以看作是下一件物品装与否的父问题,第三,当决定第一件物品装载与否的时候,即到达边界,最后,每一件物品的装与不装所造成的最后结果都是彼此独立互不影响的。因此这道题可以使用动态规划的方法来解决。

        现在来分析它的最优子结构,当物品只有一件时,只需比较这件物品的重量和包的容积,如果物品的重量大于包的容积,总价值就是物品的价值,否则总价值就是0.这也就是子问题的边界。用逻辑表达式写出来是这样子的

        if(n==1)
        {
               if(weight[0]<=sm)
                      vm = value[0];
               else
                      vm = 0;
         }

这里weight这个数组就代表每一件物品的质量,value数组代表每一件物品的价值,vm是总价值,sm是包的容积

        当n大于等于2时,对于每一个子问题(或者是父问题)都只有两种选择可以做,第一,就是选择省出空间装之前几件物品,第二,就是装本件物品,获得对应的价值,但是用去了一点包的空间。然后只需要比较这两种方案哪一种更优就选择哪一种,用逻辑表达式写出来是这样

        vm(sm,n) = max[vm(sm,n-1),value[n-1] + vm(sm-weight[n-1],n-1)]

在这个式子中,vm是总价值函数。


        这样一来,背包问题就得到了解决。

        下面贴上完整代码。

#include<stdio.h>
int beibao(int sm,int n,int weight[100],int value[100]);
int main(){
	int sm,n,vm;
	printf("请输入背包的容积和物品的件数\n");
	scanf("%d%d",&sm,&n);
	int i;
	int weight[n];
	int value[n];
	printf("请输入每一件物品的重量与价值\n");
	for(i=0;i<n;i++)
	{
		scanf("%d%d",&weight[i],&value[i]);
	}
	vm = beibao(sm,n,weight,value);
	printf("%d",vm);
	return 0;	
}
int beibao(int sm,int n,int weight[100],int value[100])
{
	
	if(n==1)
	{
		if(weight[0]<=sm)
			return value[0];
		else
			return 0;
	}
	else
	{
		if((value[n-1]+beibao(sm-weight[n-1],n-1,weight,value))>=(beibao(sm,n-1,weight,value)))
			return value[n-1]+beibao(sm-weight[n-1],n-1,weight,value);
		else
			return beibao(sm,n-1,weight,value);
	}
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值