Backtracking method with four exercises - (subset sum problem, minimum weight machine design problem, athlete best pairing problem, Romeo and Juliet's maze problem)

content

  • Subsets and Questions
  • Minimum Weight Machine Design Issues
  • Athlete's Best Matching Question
  • The Labyrinth of Romeo and Juliet

Subsets and Questions

Problem Description

write picture description here

Parse

Pay attention to the conditions for entering the left and right subtrees, record a remaining total sum, enter the right subtree only when the current sum plus the remaining sum is greater than bestSum, and then use the backtracking method to solve.

import java.io.BufferedInputStream;
import java.util.Scanner;

/**
 * 回溯法解决子集和问题
 * @author 郑鑫
 *
 */
public class SubSum {
    private int n;
    private int C; //给出的总和
    private int nowW;
    private int bestW;
    private int Cleft;
    private int[] w; //每一个的权重
    private int[] x;
    private int[] bestX;

    public SubSum(int n, int c, int nowW, int bestW, int cleft, int[] w, int[] x, int[] bestX) {
        super();
        this.n = n;
        C = c;
        this.nowW = nowW;
        this.bestW = bestW;
        Cleft = cleft;
        this.w = w;
        this.x = x;
        this.bestX = bestX;
    }

    public boolean backTrack(int i){
        if(i >= n){
            for(int j = 0; j < i; j++)bestX[j] = x[j];
            bestW = nowW;
            if(C == bestW)return true;
            return false;
        }
        Cleft -= w[i];
        if(nowW + w[i] <= C){  //进入左子树
            x[i] = 1;
            nowW += w[i];
            if(backTrack(i+1))return true;
            x[i] = 0;
            nowW -= w[i];
        }
        if(nowW + Cleft > bestW){
            x[i] = 0;
            if(backTrack(i+1))return true;
        }
        Cleft += w[i];
        return false;
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        int n = cin.nextInt(),C = cin.nextInt();
        int[] w = new int[n+1];
        int[] x = new int[n+1],bestX = new int[n+1];
        int Cleft = 0,nowW = 0,bestW = 0;
        for(int i = 0; i < n; i++){
            w[i] = cin.nextInt();
            Cleft += w[i];
        }

        SubSum ss = new SubSum(n, C, nowW, bestW, Cleft, w, x, bestX);
        ss.backTrack(0);
        //System.out.println(ss.bestW);
        for(int i = 0; i < n; i++)if(bestX[i] == 1)System.out.print(w[i] + " ");
        System.out.println();
    }
}

Minimum Weight Machine Design Issues

Problem Description

write picture description here

Parse

It is also a classic backtracking exercise.

import java.io.BufferedInputStream;
import java.util.Scanner;
/**
 * 最小重量机器设计问题
 * @author 郑鑫
 */
public class Machine {
    private static int n,m,C,nowW = 0,bestW = 0,nowV = 0;
    private static int[][] w;
    private static int[][] v;
    private static int[] x,bestX;

    private static void BackTrack(int i){
        if(i >= n){
            for(int j = 0; j < i; j++)bestX[j] = x[j];
            bestW = nowW;
            return ;
        }
        else for(int j = 0; j < m; j++){
            x[i] = j;
            nowW += w[i][j];
            nowV += v[i][j];
            if(nowV <= C && nowW < bestW)BackTrack(i+1);
            nowW -= w[i][j];
            nowV -= v[i][j];
        }
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        n = cin.nextInt();
        m = cin.nextInt();
        C = cin.nextInt();
        v = new int[n+1][n+1];w = new int[n+1][n+1];
        x = new int[n+1]; bestX = new int[n+1];
        int MAXW = 0;
        for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)v[i][j] = cin.nextInt(); 
        for(int i = 0; i < n; i++)for(int j = 0; j < n; j++){
            w[i][j] = cin.nextInt(); 
            MAXW += w[i][j];
        }
        bestW = MAXW;
        BackTrack(0);
        System.out.println(bestW);
        for(int i = 0; i < n; i++)System.out.print(bestX[i] + 1 + " ");
        System.out.println();
        cin.close();
    }
}

Athlete's Best Matching Question

Problem Description

write picture description here

Parse

Or use an array r[i] to represent the female athlete paired by the i-th male athlete, and then exchange two partners each time to see if the sum can be made larger, and if it is larger, record it

import java.io.BufferedInputStream;
import java.util.Scanner;

/**
 * 羽毛球运动员配对问题
 * @author 郑鑫
 */
public class BadmintonMatches {
    private static int[][] P,Q;
    private static int[] r,bestR;
    private static int n,bestSum;

    public static void swap(int[] arr,int a,int b){
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp; 
    }

    public static void BackTrack(int i){
        if(i >= n){
            int sum = 0; 
            for(int j = 0; j < n; j++)sum += P[j][r[j]] * Q[r[j]][j];
            if(sum > bestSum){
                bestSum = sum;
                for(int j = 0; j < n; j++)bestR[j] = r[j];
            }
        }else for(int j = i; j < n; j++){
            swap(r, i, j);
            BackTrack(i+1);
            swap(r, i, j);          
        }
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        n = cin.nextInt();
        P = new int[n+1][n+1];  Q = new int[n+1][n+1];
        r = new int[n+1];bestR = new int[n+1];
        for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)P[i][j] = cin.nextInt();
        for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)Q[i][j] = cin.nextInt();

        //r[i]表示第i个男运动员配对的女运动员
        for(int i = 0; i < n; i++)r[i] = i;  //一开始 i -> i
        for(int i = 0; i < n; i++)bestR[i] = i;
        bestSum = 0;
        BackTrack(0);
        System.out.println(bestSum);
        for(int i = 0; i < n; i++)System.out.print(i+1 + "-->" +(bestR[i]+1) + "\n");
        System.out.println();
    }
}

The Labyrinth of Romeo and Juliet

Problem Description

write picture description here

Parse

Pay attention to the function of judging out-of-bounds, and the minimum number of turns, pay attention to the judgment of turning conditions di != i , and when dep = 1, the first time is not counted as turning, and then it is also solved by backtracking.

import java.io.BufferedInputStream;
import java.util.Scanner;

public class SearchLuoMiOuYe {
    //控制方向
    private static int[] dx = {0,1,1, 1, 0,-1,-1,-1};
    private static int[] dy = {1,1,0,-1,-1,-1, 0, 1};
    //罗密欧和朱丽叶的位置
    private static int startX,startY,endX,endY;
    private static int n,m,k; //行数,列数,被封闭的房间
    private static int dirs,minn,count;
    private static int[][] board,best;

    public static boolean check(int x,int y){
        return (x > 0 && x <= n && y > 0 && y <= m && board[x][y] == 0);  
    }

    public static void Search(int x,int y,int dep,int di){
        if(dep == n*m - k && x == endX && y == endY && dirs <= minn){
            if(dirs < minn){
                minn = dirs;
                count = 1;
                for(int i = 1; i <= n; i++)
                    for(int j = 1; j <= m; j++)
                        best[i][j] = board[i][j];
            }else count++;
            return ;
        }else for(int i = 0; i < 8; i++){
            int nx = x + dx[i],ny = y + dy[i];
            if(check(nx, ny)){
                if(di != i && dep > 1)dirs++;
                board[nx][ny] = dep+1;
                Search(nx, ny, dep+1, i);
                if(di != i && dep > 1)dirs--;
                board[nx][ny] = 0;
            }
        }
    }

    public static void main(String[] args) {
        Scanner cin = new Scanner(new BufferedInputStream(System.in));
        n = cin.nextInt();
        m = cin.nextInt();
        k = cin.nextInt();
        board = new int[n+1][m+1];
        best = new int[n+1][m+1];
        for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)board[i][j] = 0;
        for(int i = 0; i < k; i++){
            int a = cin.nextInt(); int b = cin.nextInt();
            board[a][b] = -1; //标记封闭的房间 
        }
        startX = cin.nextInt();
        startY = cin.nextInt();
        endX = cin.nextInt();
        endY = cin.nextInt();

        minn = 1000000;
        board[startX][startY] = 1;
        Search(startX, startY, 1, 0);
        System.out.println(minn + "\n" + count);
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++)
                System.out.print(best[i][j] + " ");
            System.out.println();
        }
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324754882&siteId=291194637