Java動態規划實現將數組拆分成相等的兩部分


package com.array;

import java.util.Scanner;
import java.util.Vector;

class partionArray{
    private Vector<Integer>arr=new Vector<Integer>();
    private int sum=0;
    private Scanner iner=new Scanner(System.in);
    private int memo[][];
    
    public boolean Solution() {
        System.out.print("請輸入元素:");    
        for(int i=0;i<4;++i) {
            arr.add(i, iner.nextInt());
            sum+=arr.elementAt(i);
        }
        
        if(sum%2==0&&sum!=0) {
         memo=new int[sum/2+1][sum/2+1];
         return isPartied(arr,0,sum/2);
        }        
        else 
         return false;
            
    }
    /***
     * 對數組中的每個元素采用放與不放
     * 看那種滿足條件
     * 動態規划等於窮舉加剪枝
     * 剪枝就類似於記憶化--對一些不必要的操作進行簡化
     * 因此用遞歸時要加上記憶化
     * 沒有記憶化會導致超時
     * @return
     */
    public boolean isPartied(Vector<Integer>arr,int Index,int c) {
        if(Index==arr.size()-1) {
            return c==0;
        }
        if(c==0) {
            return true;
        }
        if(memo[Index][c]!=0) {
            return memo[Index][c]==1;      //在這一步成功的將int類型的值轉變為boolean類型的值
        }
        //在這里對接下來的程序進行記憶化攔截
        if(isPartied(arr,Index+1,c)||isPartied(arr,Index+1,c-arr.elementAt(Index))) {
            memo[Index][c]=1;
            return true;
        }
        memo[Index][c]=-1;       //將結果記錄下來
        return false;
        
    }
}

/***
 * 動態規划的寫法,自底向上的寫法,遞推--從一個最優解推出另一個最優解
 * 動態規划問題的核心思想是:1、要求什么dp數組中就放什么,再去填寫dp table 
 * 2、要將的大問題分解為一個一個的小問題,例如有多個元素要處理
 * 則先考慮一種情況使其的結果為最優再逐漸推出其他的最優解從而解決問題
 * 所謂的窮舉就是把所有的情況都列舉出來通過一定的手段去剪枝
 * @author Administrator
 */
class partionArray2{
    
    private Vector<Integer>arr=new Vector<Integer>();
    private int sum=0;
    private Scanner iner=new Scanner(System.in);
    private boolean dp[][];
    
    public boolean Solution() {
        System.out.print("請輸入元素:");    
        for(int i=0;i<4;++i) {
            arr.add(i, iner.nextInt());
            sum+=arr.elementAt(i);
        }
        if(sum%2==0) {
            int n=sum/2;
            dp=new boolean[n+1][n+1];
            for(int i=0;i<n;++i) {
                dp[0][i]=arr.elementAt(0).equals(i);
            }
            for(int i=1;i<arr.size();++i) {
                for(int j=0;j<=n;++j) {
                    if(j>arr.elementAt(i)) {       
                        dp[i][j]=dp[i-1][j-arr.elementAt(i)];//如果大於的話就看它的dp[i][j]=dp[i-1][j-arr.elementAt(i)]為不為true,如果為true則這個也為true
                    }
                    if(j==arr.elementAt(i)) {   //相等則賦值為true,因為只有在它的子序列中找到一個能正好填滿背包的值就可以
                        dp[i][j]=true;
                    }
                    else {    //小於時保持上一次的值
                        dp[i][j]=dp[i-1][j];
                    }
                }
            }
            return dp[arr.size()-1][n];
        }
        return false;
            
    } 
    
}

public class Main {
  public static void main(String[] args) {
    partionArray2 space=new partionArray2();
    System.out.println(space.Solution());
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM