基础算法题

基础算法

计算最大公约数和最小公倍数

最大公约数GCD:欧几里得算法(辗转相除法)
原理:

如果b是a的余数,那么a和b的最大公约数就是b和a%b的最大公约数,当b为0时,a就是最大公约数

最小公倍数LCM:

LCM=|a*b|/GCD(a,b)

代码:

public class GCDLCM{
	public static void main(String[] args){
		int num1=315;
		int num2=210;
		int gcdResult=gcd(num1,num2);
		int lcmResult=lcm(num1,num2);
		System.out.println(num1+"和"+num2+"的最大公约数是"+gcdResult);
		System.out.println(num1+"和"+num2+"的最小公倍数是"+lcmResult);
	} 
	public static int gcd(int a,int b){
		while(b!=0){
			int temp=b;
			b=a%b;
			a=temp;
		}
		return a;
	}
	public static int lcm(int a,int b){
		return Math.abs(a*b)/gcd(a,b);
	}
}

01背包

1.题目

有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?

2.例子

number=4,capacity=8

物品编号(i) W(体积) V(价值)
1 2 3
2 3 4
3 4 5
4 5 6

3.实现

动态规划
  1. 什么是动态规划
    1. 动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,
      使得问题能够以递推(或者说分治)的方式去解决。
    2. 动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),
      按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。
      在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,
      丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

2.对题目分析
1.分析
面对每个物品,我们只有选择拿取或者不拿两种选择,不能选择装入某物品的一部分,也不能装入同一物品多次。
解决办法:声明一个 大小为 m[n][c]的二维数组,m[ i ][ j ] 表示 在面对第 i 件物品,且背包容量为 j 时所能获得的最大价值 ,那么我们可以很容易分析得出 m[i][j] 的计算方法,
(1) j < weight[i] 的情况,这时候背包容量不足以放下第 i 件物品,只能选择不拿
m[ i ][ j ] = m[ i-1 ][ j ]
(2). j>=w[i] 的情况,这时背包容量可以放下第 i 件物品,我们就要考虑拿这件物品是否能获取更大的价值
如果拿取,m[ i ][ j ]=m[ i-1 ][ j-weight[ i ] ] + value[ i ]。 这里的m[ i-1 ][ j-weight[ i ] ]指的就是考虑了i-1件物品,背包容量为j-w[i]时的最大价值,也是相当于为第i件物品腾出了w[i]的空间。
如果不拿,m[ i ][ j ] = m[ i-1 ][ j ] , 同(1)
究竟是拿还是不拿,自然是比较这两种情况那种价值最大。

2.状态转换方程

if(j>=w[i])
    m[i][j]=max(m[i-1][j],m[i-1][j-weight[i]]+value[i]);
else
    m[i][j]=m[i-1][j];

3.状态转换图

img1)如,i=1,j=1,w(1)=2,v(1)=3,有j<w(1),故V(1,1)=V(1-1,1)=0;

  1. 又如i=1,j=2,w(1)=2,v(1)=3,有j=w(1),故V(1,2)=max{ V(1-1,2),V(1-1,2-w(1))+v(1) }=max{0,0+3}=3;
  2. 如此下去,填到最后一个,i=4,j=8,w(4)=5,v(4)=6,有j>w(4),故V(4,8)=max{ V(4-1,8),V(4-1,8-w(4))+v(4) }=max{9,4+6}=10;所以填完表如下图:

完整代码:

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //在此输入您的代码...
        int totalWeight=scan.nextInt();//背包的总容量
        int N=scan.nextInt();//物品的数量
        int W[]=new int[N+1];//物品的容量
        int V[]=new int[N+1];//物品的价值
        for(int i=0;i<N;i++){
          W[i]=scan.nextInt();
          V[i]=scan.nextInt();
        }
        scan.close();
        int[][] dp=new int[N+1][totalWeight+1];
        for(int i=1;i<=N;i++){
          for(int j=0;j<=totalWeight;j++){
            if(W[i]>j){
              dp[i][j]=dp[i-1][j];//放不进
            }else{
            dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-W[i]]+V[i]);//能放进去的话比较放与不放,选择最优解
            }
          }
         
        }
         System.out.println(dp[N][totalWeight]);

        
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值