• 两道关于回溯法,分支限界法的算法题


    1.最小重量机器设计问题:设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设 wij    是从供应商j处购得的部件 i 的重量, cij 是相应的价格。试设计一个算法,给出总价格不超过 c 的最小重量机器设计。

    方法一:回溯法设计:

    import static org.junit.Assert.*;
    
    import java.util.Scanner;
    
    import org.junit.Test;
    
    public class 最小重量机器 {
        
        /*
         * 3 3
         * 3 2  1 4  5 6
         * 1 4  3 2  5 6
         * 5 6  3 2  1 4
         * 10
         * 
         * 答案是5
         */
        private static int w[][];
        private static int c[][];
        private static int vis[][];
        private static int n, m, cc;
        private static int ans;
        private static Scanner cin;
        static{
            cin = new Scanner(System.in);
        }
        private static void init() {
            for(int i = 0; i < n; i++){
                for(int j = 0; j < m; j++){
                    vis[i][j] = 0;
                }
            }
            ans = Integer.MAX_VALUE;
        }
        public static void main(String[] args) {
            System.out.println("请输入部件数目以及供货商数量n和m:");
            n = cin.nextInt();
            m = cin.nextInt();
            w = new int[n][m];
            c = new int[n][m];
            vis = new int[n][m];
            System.out.println("n行代表n个部件,每行输入每个供货商供应此部件的重量以及价格:");
            for(int i = 0; i < n; i++){
                for(int j = 0; j < m; j++){
                    w[i][j] = cin.nextInt();
                    c[i][j] = cin.nextInt();
                }
            }
            System.out.println("请输入不超过的价格p:");
            cc = cin.nextInt();
            init();
            work(0, cc, 0, 0);
            if(ans == Integer.MAX_VALUE){
                System.out.println("不能找出总价格不超过 c的最小重量机器的方案");
            }else{
                System.out.println("满足方案的最小重量是:" + ans);
            }
        }
        private static void work(int i, int cc, int ww, int p){
            if(i == n){
                if(p <= cc){
                    ans  = Math.min(ans, ww);
                }
                return;
            }
            for(int j = 0; j < m; j++){
                vis[i][j] = 1;
                work(i + 1, cc, ww + w[i][j], p + c[i][j]);
                vis[i][j] = 0;
            }
            
        }
        
    }

     分支限界法:

    import static org.junit.Assert.*;
    
    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Scanner;
    
    import javax.management.Query;
    
    import org.junit.Test;
    
    class Node{
        private int curw, curv;
        private int units_i;
        private int[] route;
        Node(){
            route = new int[110];
        }
        public Node(int curw, int curv, int units_i, int[] route) {
            super();
            this.curw = curw;
            this.curv = curv;
            this.units_i = units_i;
            this.route = route;
        }
        public int getCurw() {
            return curw;
        }
        public void setCurw(int curw) {
            this.curw = curw;
        }
        public int getCurv() {
            return curv;
        }
        public void setCurv(int curv) {
            this.curv = curv;
        }
        public int getUnits_i() {
            return units_i;
        }
        public void setUnits_i(int units_i) {
            this.units_i = units_i;
        }
        public int[] getRoute() {
            return route;
        }
        public void setRoute(int[] route) {
            this.route = route;
        }
        
    }
    
    public class 最小重量设计_分支限界法 {
        
        /*
         * 3 3
         * 3 2  1 4  5 6
         * 1 4  3 2  5 6
         * 5 6  3 2  1 4
         * 10
         * 
         * 答案是5
         */
        private static int w[][];
        private static int c[][];
        private static int n, m, cc;
        private static Scanner cin;
        private static Queue<Node>q;
        static{
            cin = new Scanner(System.in);
            q = new LinkedList<Node>();
        }
    
    
        public static void main(String[] args) {
            System.out.println("请输入部件数目以及供货商数量n和m:");
            n = cin.nextInt();
            m = cin.nextInt();
            w = new int[n][m];
            c = new int[n][m];
            
            System.out.println("n行代表n个部件,每行输入每个供货商供应此部件的重量以及价格:");
            for(int i = 0; i < n; i++){
                for(int j = 0; j < m; j++){
                    w[i][j] = cin.nextInt();
                    c[i][j] = cin.nextInt();
                }
            }
            System.out.println("请输入不超过的价格p:");
            cc = cin.nextInt();
            q.clear();
            int[] route = new int[110];
            Node e = new Node(0, 0, -1, route);
            q.add(e);
            int ans = Integer.MAX_VALUE;
            while(!q.isEmpty()){
                e = q.poll();
                
                for(int j = 0; j < m; j++){
                    int i = e.getUnits_i() + 1;
                    if(i >= n){
                        
                        if(e.getCurv() <= cc){
                            if(ans > e.getCurw()){
                                ans = Math.min(ans, e.getCurw());
                                route = e.getRoute();
                            }
                        }
                        continue;
                    }
                    int curv = e.getCurv() + c[i][j];
                    int curw = e.getCurw() + w[i][j];
                    
                    int[] lastroute = e.getRoute();
                    int[] curroute = new int[110];
                    for(int k = 0; k <= e.getUnits_i(); k++){
                        curroute[k] = lastroute[k];
                    }
                    curroute[i] = j;
                    
                    q.add(new Node(curw, curv, i, curroute));
                }
            }
            if(ans == Integer.MAX_VALUE){
                System.out.println("不能找出总价格不超过 c的最小重量机器的方案");
            }else{
                System.out.println("满足方案的最小重量是:" + ans);
                System.out.println("方案是:");
                for(int j = 0; j < n; j++){
                    System.out.print(route[j] + " ");
                }
                
            }
        }
        
        
    }


    2.最大 k 乘积问题: 设    I 是一个 n 位十进制整数。如果将 I 划分为 k 段,则可得到    k 个整数。这 k 个整数的乘积称为 I 的一个 k 乘积。试设计一个算法,对于给定的 I 和 k ,求出 I 的最大 k 乘积。

    回溯法设计:

    import java.util.Scanner;
    
    
    public class 最大k成绩 {
        private static long ans;
        private static Scanner cin;
        static{
            cin = new Scanner(System.in);
        }
        static void work(int cur, int i, int k, long v){
            //System.out.println("i = " + i + " cur = " + cur + " k = " + k);
            if(i == k){
                ans = Math.max(ans, v);
                return;
            }
            if(cur == 0){
                return;
            }
            int MOD = 1;
            while(cur / MOD != 0){
                work(cur % MOD, i + 1, k, v * (cur / MOD));
                MOD *= 10;
            }
        }
        public static void main(String[] args) {
            int num, k;
            System.out.println("请输入数字num和要分成的段数k: ");
            while(cin.hasNext()){
                num = cin.nextInt();
                k = cin.nextInt();
                ans = Long.MIN_VALUE;
                work(num, 0, k, 1L);
                if(ans == Long.MIN_VALUE){
                    System.out.println("整数" + num + "不能被分成" + k + "段");
                }else{
                    System.out.println(num + "的最大" + k + "乘积是: " + ans);
                }
                System.out.println("请输入数字num和要分成的段数k: ");
            }
        }
    }
  • 相关阅读:
    上传图片时判断图片的模式GRB或CMYK
    正则表达式的6中使用
    SqlServer获得存储过程的返回值
    从零学习wcf(一)
    等比例缩小图片
    模仿Jquery Tab
    jquery ajax调用一般处理程序
    一种感觉
    "敏捷软件开发" 读书笔记叙
    荣迁贵宝地
  • 原文地址:https://www.cnblogs.com/handsomecui/p/6227212.html
Copyright © 2020-2023  润新知