暴力递归到动态规划

本文探讨了将暴力递归转化为动态规划的适用条件和常见模型,包括从左往右尝试、范围上的尝试和N皇后问题。通过案例分析,展示了如何从暴力递归逐步优化为动态规划,以提高算法效率并解决复杂问题。
摘要由CSDN通过智能技术生成

动态规划的适用条件

  • 总结

    • 从左到右尝试的模型
    • 范围上的尝试模型
    • 多样本位置全对应的尝试模型
    • 寻找业务限制的尝试模型
  • 总结
    题->找到暴力递归方法(尝试,具有重复解)->可变参数,不讲解组织->记忆化搜索->精细化组织->经典的动态规划

从左往右尝试的模型1

规定1和A对应,2和b对应,3与c对应,那么一个字符串,比如"111"就可以转化为:“AAA”,“KA”,“AK”,给定一个只有数字字符组成的字符串str,返回多少种转化结果。

暴力递归

package Digui;
public class convertLetterString {
   
	//str只包含数字字符
	//返回多少种转化方案
	 public static int num(String str){
   
		 if (str==null||str.length()==0) {
   
			return 0;
		}
		 return process(str.toCharArray(), 0);
	 }
	//str[0...i-1]已经转化完了,固定了
	//i之前的位置,如何转化已经做好决定了,不用再关心
	//i..之后有多少种转化结果
	public static int process(char[] str,int i){
   
		if (i==str.length) {
   
			return 1;//两种解释,没有字符的时候能不能转化,能,转化为1
			//我找到一种有效的转化,str[0...i-1]已经转化完了,固定了,所以终止位置,我收集一点答案1.
			//"11"变为“AA","K"
		}
		//i没有到终止位置
		if (str[i]=='0') {
   
			return 0;
		}
		//str[i]不是‘0’
		if (str[i]=='1') {
   
			int res=process(str, i+1);//i自己作为单独部分,后续有多少转化
			if (i+1<str.length) {
   
				res+=process(str, i+2);//i和i+1自己作为单独部分,后续有多少转化
			}	
			return res;
		}
		if (str[i]=='2') {
   
			int res=process(str, i+1);//i自己作为单独部分,后续有多少转化
			//i和i+1自己作为单独部分,并没有
			if (i+1<str.length && str[i+1]>='0'&&str[i+1]<='6') {
   
				res+=process(str, i+2);//i和i+1自己作为单独部分,后续有多少转化
			}	
			return res;
		}
		//str[i]为'3'-'9'
		return process(str, i+1);
	}
	public static void main(String[] args) {
   
		String str="111";
		System.out.println(num(str));
	}
}
//3.AAA,AK,KA

动态规划

package Digui;
public class convertLetterStringdp {
   
		public static int dpways(String s){
   
			if (s==null||s.length()==0) {
   
				return 0;
			}
			char[] str=s.toCharArray();
			int N=s.length();
			int[] dp=new int [N+1];
			dp[N]=1;
			for(int i=N-1;i>=0;i--){
   
				if (str[i]=='0') {
   
					dp[i]=0;
				}
				if (str[i]=='1') {
   
					dp[i]=dp[i+1];
					if (i+1<str.length) {
   
						dp[i]+=dp[i+2];
					}	
				}
				if (str[i]=='2') {
   
					dp[i]=dp[i+1];
					if (i+1<str.length && str[i+1]>='0'&&str[i+1]<='6') {
   
						dp[i]+=dp[i+2];
					}	
				}
			}	
			return dp[0];
		}
		public static void main(String[] args) {
   
			String str="111";
			System.out.println(dpways(str));
		}
}

从左往右尝试的模型2

给定两个长度都为N的weights和values,weights[i]和values[i]分别代表i号物品的重量和价值,给定一个正数bag,表示一个载重的bag的袋子。给定一个正数bag,表示一个载重bag的袋子。你装的物品不能超过这个重量。返回你能装下最多的价值是多少?

暴力递归版

package Digui;
public class knaspack {
   
	public static int getMaxvalue(int[] w,int [] v,int bag){
   
		return Process(w,v,0,0,bag);
	}
	//不变,v[],w[],bag
	//index..最大价值
	//0..index-1做了货物选择,使你已经达到的重量是多少alreadyW
	//如果返回-1,则认为没有这个方案。返回不是-1,则返回的值是一个真实的价值
	public static int Process(int[] w,int [] v,int index,int alreadyW,int bag ){
   
		if (alreadyW>bag) {
   
			return -1;
		}
		//重量没超
		if (index==w.length) {
   
			return 0;
		}
		//没有要当前的货,后续的最大价值
		int p1=Process(w, v, index+1, alreadyW, bag);
		//要了当前的货,后面的货最大的价值
		int p2next=Process(w, v, index+1, alreadyW+w[index], bag);
		int p2=-1;
		if (p2next!=-1) {
   
			p2=v[index]+p2next;
		}
		return Math.max(p1, p2);
	}
	public static void main(String[] args) {
   
		int[] weights = {
    3, 2, 4
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值