基础算法
计算最大公约数和最小公倍数
最大公约数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.实现
动态规划
- 什么是动态规划
- 动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,
使得问题能够以递推(或者说分治)的方式去解决。 - 动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),
按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。
在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,
丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。
- 动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,
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.状态转换图
1)如,i=1,j=1,w(1)=2,v(1)=3,有j<w(1),故V(1,1)=V(1-1,1)=0;
- 又如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;
- 如此下去,填到最后一个,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]);
}
}