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());
  }
}

猜你喜欢

转载自www.cnblogs.com/z2529827226/p/11625373.html
今日推荐