【算法】-动态规划01
背包问题
1.0-1背包问题
每个背包只能用一次
朴素算法
import java.lang.*; import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc=new Scanner(System.in); int N=sc.nextInt(); int V=sc.nextInt(); int[] weights=new int[1001]; int[] values=new int[1001]; for(int cur=1;cur<=N;cur++){ weights[cur]=sc.nextInt(); values[cur]=sc.nextInt(); } int tmp=V; int[][] dp=new int[1001][1001]; for(int i=1;i<=N;i++){ for(int j=1;j<=V;j++){ if(j>=weights[i]){ dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-weights[i]]+values[i]); }else{ dp[i][j]=dp[i-1][j]; } } } System.out.println(dp[N][V]); } }
滚动数组优化算法
import java.lang.*; import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc=new Scanner(System.in); int N=sc.nextInt(); int V=sc.nextInt(); int[] weights=new int[1001]; int[] values=new int[1001]; for(int cur=1;cur<=N;cur++){ weights[cur]=sc.nextInt(); values[cur]=sc.nextInt(); } int[] dp=new int[1001]; for(int i=1;i<=N;i++){ for(int j=V;j>=0;j--){ if(j>=weights[i]){ dp[j]=Math.max(dp[j],dp[j-weights[i]]+values[i]); } } } System.out.println(dp[V]); } }
2.完全背包问题
每个物品可以装无限多个
朴素算法代码
import java.lang.*; import java.util.*; class Main{ public static void main(String[] args){ Scanner scanner=new Scanner(System.in); int N=scanner.nextInt(); int V=scanner.nextInt(); final int num=1001; int[] weight_arr=new int[num]; int[] value_arr=new int[num]; for(int i=1;i<=N;i++){ weight_arr[i]=scanner.nextInt(); value_arr[i]=scanner.nextInt(); } int[][] dp=new int[num][num]; for(int i=1;i<=N;i++){ for(int j=0;j<=V;j++){ dp[i][j]=dp[i-1][j]; for(int t=0;t*weight_arr[i]<=j;t++){ dp[i][j]=Math.max(dp[i][j],dp[i-1][j-t*weight_arr[i]]+value_arr[i]*t); } } } System.out.println(dp[N][V]); } }
滚动数组代码
import java.lang.*; import java.util.*; class Main{ public static void main(String[] args){ Scanner scanner=new Scanner(System.in); int N=scanner.nextInt(); int V=scanner.nextInt(); final int num=1001; int[] weight_arr=new int[num]; int[] value_arr=new int[num]; for(int i=1;i<=N;i++){ weight_arr[i]=scanner.nextInt(); value_arr[i]=scanner.nextInt(); } int[] dp=new int[num]; for(int i=1;i<=N;i++){ for(int j=0;j<=V;j++){ for(int t=0;t*weight_arr[i]<=j;t++){ dp[j]=Math.max(dp[j],dp[j-t*weight_arr[i]]+value_arr[i]*t); //等价于dp[i][j]的下一行代码 //dp[i][j]=Math.max(dp[i][j],dp[i][j-t*weight_arr[i]]+t*value_arr[i]); } } } System.out.println(dp[V]); } }
公式优化
import java.lang.*; import java.util.*; class Main{ public static void main(String[] args){ Scanner scanner=new Scanner(System.in); int N=scanner.nextInt(); int V=scanner.nextInt(); final int num=1001; int[] weight_arr=new int[num]; int[] value_arr=new int[num]; for(int i=1;i<=N;i++){ weight_arr[i]=scanner.nextInt(); value_arr[i]=scanner.nextInt(); } int[] dp=new int[num]; for(int i=1;i<=N;i++){ for(int j=0;j<=V;j++){ for(int t=1;t*weight_arr[i]<=j;t++){ dp[j]=Math.max(dp[j],dp[j-weight_arr[i]]+value_arr[i]); } } } System.out.println(dp[V]); } }
3.多重背包问题
每个物品有有限多个
暴力算法代码
import java.lang.*; import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc=new Scanner(System.in); int N=sc.nextInt(); int V=sc.nextInt(); int[] weights=new int[101]; int[] values=new int[101]; int[] counts=new int[101]; for(int cur=1;cur<=N;cur++){ weights[cur]=sc.nextInt(); values[cur]=sc.nextInt(); counts[cur]=sc.nextInt(); } int[][] dp=new int[101][101]; for(int i=1;i<=N;i++){ for(int j=1;j<=V;j++){ dp[i][j]=dp[i-1][j]; for(int s=1;s<=counts[i]&&s*weights[i]<=j;s++){ dp[i][j]=Math.max(dp[i][j],dp[i-1][j-s*weights[i]]+s*values[i]); } } } System.out.println(dp[N][V]); } }
当数据量较大的时候,暴力解法就会超时
这时候 将第i个物品根据数量转换成多个不同的物品(二进制表示法)
import java.lang.*; import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc=new Scanner(System.in); int N=sc.nextInt(); int V=sc.nextInt(); int[] weights=new int[25000]; int[] values=new int[25000]; int[] dp=new int[26000]; int cnt=0; for(int cur=1;cur<=N;cur++){ int w=sc.nextInt(); int v=sc.nextInt(); int num=sc.nextInt(); int tmp=1; while(tmp<=num){ weights[++cnt]=tmp*w; values[cnt]=tmp*v; num-=tmp; tmp*=2; } if(num>0){ weights[++cnt]=num*w; values[cnt]=num*v; } } //此时物品数量为cnt,而不是N for(int i=1;i<=cnt;i++){ for(int j=V;j>=weights[i];j--){ dp[j]=Math.max(dp[j],dp[j-weights[i]]+values[i]); } } System.out.println(dp[V]); } }
4.分组背包问题
有若干组物品,每组物品有若干个物品
import java.lang.*; import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc=new Scanner(System.in); int N=sc.nextInt(); int V=sc.nextInt(); int[] groups=new int[N+1]; int[][] weights=new int[101][101]; int[][] values=new int[101][101]; for(int cur=1;cur<=N;cur++){ groups[cur]=sc.nextInt(); for(int cur1=1;cur1<=groups[cur];cur1++){ weights[cur][cur1]=sc.nextInt(); values[cur][cur1]=sc.nextInt(); } } int[] dp=new int[V+1]; for(int i=1;i<=N;i++){ for(int j=V;j>=1;j--){ for(int g=1;g<=groups[i];g++){ if(j>=weights[i][g]) dp[j]=Math.max(dp[j],dp[j-weights[i][g]]+values[i][g]); } } } System.out.println(dp[V]); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现