递归(重点:递推公式+终止条件)
1.找到如何将大问题分解为小问题的规律
2.通过规律写出递推公式
3.通过递归公式的临界点推敲出终止条件
4.将递推公式和终止条件翻译成代码
动态规划
1.动态规划法试图只解决每个子问题一次
2.一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。如:每一次迭代过程中,只需要保留之前的两个状态,就可以推到出新的状态。
「动态规划」中包含三个重要的概念:
- 【最优子结构】
- 【边界】
- 【状态转移公式】
- 在「 爬台阶问题 」中:
- f(10) = f(9) + f(8) 是【最优子结构】
- f(1) 与 f(2) 是【边界】
- f(n) = f(n-1) + f(n-2) 【状态转移公式】
- 在「 爬台阶问题 」中:
挖金矿
- N是金矿数量,W是人数,P[ ]是每个金矿所需人数,G[ ]是每个金矿的价值
- N=5
- W=10
- P[ ]={5,5,3,4,3}
- G[ ]={400,500,200,300,350}
最优子结构
边界
- 当N<=1,W<P[0]时,F(N,W)=0;
- 当N==1,W>=P[0]时,F(N,W)=G[0];
状态转移方程
- 当N>1,W<P[N-1]时,F(N,W)=F(N-1,W);
- 当N>1,W>=P[N-1]时,F(N,W)=MAX(F(N-1,W),F(N-1,W-P[N-1])+G(N-1));
他给的代码运行不出来,还得自己找,不知道是不是因为c和Java的差异问题
public class testdp {
static void getMostGold(){
int p[] = {5,5,3,4,3};
int g[]={400,500,200,300,350};
int n=5,w=10;//w是人数,n是金矿数量
int[]preResults=new int[w+1];
int[]results=new int[w+1];
//填充边界格子的值
for(int i=0;i<=w;i++){
if(i<p[0]){
preResults[i]=0;
}else{
preResults[i]=g[0];
}
}
//填充其余格子的值,外层循环是金矿数量,内层循环是工人数
for(int i=0;i<p.length;i++){
for(int j=0;j<=w;j++){
if(j-p[i]<0){
results[j]=preResults[j];
}else {
results[j]=Math.max(preResults[j],preResults[j-(p[i])]+g[i]);
}
}
System.arraycopy(results, 0, preResults, 0, 11);
//preResults=Arrays.copyOf(results, results.length);
}
System.out.println(results[w]);
}
public static void main(String[] args) {
getMostGold();
}
}
arraycopy
public static void arraycopy(Object src, //src - 源数组。
int srcPos, //srcPos - 源数组中的起始位置。
Object dest, //dest - 目标数组
int destPos, //destPos - 目标数据中的起始位置
int length) //length - 要复制的数组元素的数量