动态规划(转载)

http://www.cnblogs.com/sdjl/articles/1274312.html

import java.util.Scanner ;

public class Max{
	private int[] peopleNeed ; //每座金矿需要的人数 ;
	private int[] gold ;       //每座金矿能够挖出来的金子数 ; 
	private int[][] maxGold ;  //maxGold[i][j]保存了i个人挖前j个金矿能够得到的最大金子数,等于-1表示未知

	public Max(int peopleTotal, int n){
		
		peopleNeed = new int[n] ;
		gold = new int[n] ;
		maxGold = new int[peopleTotal][n] ;//等于-1表示未知,对应动态规划中的“备忘录”;
		
		for(int i=0;i<peopleTotal;i++) {
			for(int j=0;j<n;j++){
				maxGold[i][j] = -1 ;
			}
		}
	}

	public int getMaxGold(int people, int mineNum){//获得在仅有people个人和mineNum个金矿时能够得到的最大金子数,注意“前多少个”也是从0开始编号;
		if(maxGold[people][mineNum]!=-1){      //首先查看备忘录是否有记录,若有,直接返回即可;
			return maxGold[people][mineNum] ;
		}else{
			int retMaxGold ;               //若无,进行计算 ;
			if(mineNum==0){                //检查边界情况 ;
				if(people>=peopleNeed[mineNum]){
					retMaxGold = gold[mineNum] ;
				}else{
					retMaxGold = 0 ;
				}
			}else{          
				if(people>=peopleNeed[mineNum]){     //如果给出的人能够开采这座金矿 ;
					int a = getMaxGold(people-peopleNeed[mineNum],mineNum-1) + gold[mineNum] ;
					int b = getMaxGold(people,mineNum-1) ;
					retMaxGold = Math.max(a, b) ;
				}else{                               //如果给出的人不能开采这座金矿 ;
					retMaxGold = getMaxGold(people,mineNum-1) ;
				}
			}
			maxGold[people][mineNum] = retMaxGold ;       //记录在备忘录中
			return retMaxGold ;
		}
	}
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in) ;
		int people = sc.nextInt() ;         //输入总人数 ;
		int n = sc.nextInt() ;              //输入金矿数 ;

		Max m = new Max(people,n) ;		
		for(int i=0;i<n;i++){
			m.peopleNeed[i] = sc.nextInt() ;
			m.gold[i] = sc.nextInt() ;
		}

		System.out.println(m.getMaxGold(people-1,n-1)) ;  //输出给定 people 个人和 n 个金矿所能获得的最大金子数,再次提醒编号从0开始,所以最后一个金矿编号为 n-1 ;
	} 
}

  

posted @ 2016-10-09 11:38  独孤一方  阅读(244)  评论(0)    收藏  举报