【算法】-动态规划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]);

    }
}

 

posted @ 2022-10-28 18:33  王广元  阅读(16)  评论(0编辑  收藏  举报
分享到: