递归和动态规划
裸题如下:
https://www.luogu.com.cn/problem/P1060
递归
递归的思路如下:
- 思考递归边界。
- 确定最后应该向上层返回什么东西(例如这里向上层返回的就是权重值)
- 思考应该做什么重复的事(例如这里就是对是否买玩具做判断)。
- 思考应该向下面传递什么参数(例如这里就是(玩具数组索引,兜里剩的钱,当前已经攒了多少权重))
完成以上思路很轻松就能写出以下代码。
import java.util.*; public class Main{ static int N,m; static int v[],w[]; static int _get(int deep,int money,int value){ if(deep==-1){ return value; } if(money<v[deep]){ return _get(deep-1, money, value); } int l = _get(deep-1, money, value); int r = _get(deep-1, money-v[deep], value+w[deep]); return r>l?r:l; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); m = sc.nextInt(); N = sc.nextInt(); v=new int[N+5]; w=new int[N+5]; for(int i=0;i<N;i++){ v[i] = sc.nextInt(); w[i] = sc.nextInt()*v[i]; } System.out.println(_get(N, m, 0)); } }
DP:
动态规划的思路如下:
- 确定每个可能遇到的状态 例如这道题就是确定遇到
f(n,m)
时的状态,当并将每个值保存到f[n][m]
的二维数组中。每个f(n,m)
的意义是兜里还有m块钱,想买玩具已经规划到第n个了, - 确定每个可能遇到的状态 如何找到上一个状态例如
f[i][j]
的上一个状态可能就是f[i-1][j]
- 确定状态转移方程这道题的状态转移方程就是:
f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i])
;
import java.util.*; public class P1060{ static int n,m; static int v[],w[]; public static void main(String[] args) { Scanner sc = new Scanner(System.in); m = sc.nextInt(); n = sc.nextInt(); v=new int[n+5]; w=new int[n+5]; int[][] f=new int[n+5][m+5]; for(int i=1;i<=n;i++){ v[i] = sc.nextInt(); w[i] = sc.nextInt()*v[i]; } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ //买不起 if(j<v[i]){ f[i][j] = f[i-1][j]; } else{ f[i][j] = f[i-1][j]>f[i-1][j-v[i]]+w[i]? f[i-1][j]:f[i-1][j-v[i]]+w[i]; } } } System.out.println(f[n][m]); } }
来源:https://www.cnblogs.com/godoforange/p/12271799.html