牛吃草 [PSA] EOlymp - 15 JAVA DP

E - 牛吃草 [PSA]

 EOlymp - 15 

问题描述

Alice在山上放牛,发现前方有一块矩形的优质草场。草场共有M×N个小格,每个格子有一棵牧草,用一个整数描述一棵牧草的品质。牛从左下角进入草场开始,吃完一个格子中的牧草之后,只能向右或向前继续吃,并且最后吃到草场的右上角。Alice希望牛能吃到的牧草的品质之和尽量大。请你帮Alice规划一下牛吃草的路线。

数据输入

第一行是由空格分开的两个整数M,N,表示草场的大小。 接下来有M行,每行中有N个数字,分别表示各格子中的牧草品质。

  • 0 < N,M ≤ 100
  • 牧草的品质是[0,30000]的整数

数据输出

用R表示向右走,用F表示向前走。在一行中输出从左下角出发,到右上角的一条路径,使得牛吃到的牧草品质之和最大。

样例

输入样例

2 3
3 2 4
1 5 1

输出样例

RFR

 

本来以为这是一个简单的搜索题,从左下的点开始,不断向上或向右递归搜索到最终的右上角,找到其中的最大路径即可。

但实际上,这样的BFS只能过4/14的测试点,超时严重

不得已,剪枝是不可能剪枝的,差的太多了,那就换个思路

认真一想,这应该是道动态规划的题,设dp[N]的值是点N到起始点1的最大值(最优解),arr[N]是点4的值

假设编号:

3 4

1 2

那个dp[4]=max{dp[3],dp[2]}+arr[4]

显然我们可以得到如下规律

dp[X]=max{dp[X左],dp[X下]}+arr[X]

类似的 换成二位同样的道理,从右上角出发,向左下角进军

dp(i,j)=max{dp(i,j-1), dp(i+1,j)}+arr[i][j]

因为题目需要的是输出路线,所以需要加个路线图ans,最优是向左的就比之加个R,向下就加个F

代码: 写带记忆的自顶向下的DP还是要一点技巧的,熟练的话就会发现结构大体相同,唯一需要注意的是ans放remb之后

import java.util.Scanner;

public class Main{
	static long[][] arr;
	static long[][] remb;
	static int m,n;
	static String[][] ans;//路线图
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		m = sc.nextInt();
		n = sc.nextInt();
		arr = new long[m][n];
		for (int i = 0; i < arr.length; i++) {
			for (int j = 0; j < arr[i].length; j++) {
				arr[i][j]=sc.nextInt();
			}
		}
		remb = new long[m][n];
		ans = new String[m][n];
		for (int i = 0; i < ans.length; i++) {
			for (int j = 0; j < ans[i].length; j++) {
				ans[i][j]="";
			}
		}
		long maxvalue=dp(0,n-1);	//最大值
		System.out.println(ans[0][n-1]);	//输出路线
	}
	static long dp(int i,int j) {
		if(remb[i][j]!=0)	//带记忆的自顶向下DP
			return remb[i][j];
		if(i+1=0) {
				if(dp(i,j-1)> dp(i+1,j)) {
					remb[i][j] = dp(i,j-1)+arr[i][j];	//注意发挥remb的作用 不要直接return 
					ans[i][j] = ans[i][j-1]+"R";	//注意ans要在remb之后!
				}
				else {
					remb[i][j] = dp(i+1,j)+arr[i][j];
					ans[i][j] = ans[i+1][j]+"F";			
				}
			}
			else {
				remb[i][j] = dp(i+1,j)+arr[i][j];
				ans[i][j] = ans[i+1][j]+"F";		
			}
		else
			if(j-1>=0) {
				remb[i][j] = dp(i,j-1)+arr[i][j];
				ans[i][j] = ans[i][j-1]+"R";
			}
			else
				remb[i][j] = arr[i][j];
		return remb[i][j];		//最后一起return即可
	}
}

 

你可能感兴趣的:(OJ,Test,JAVA,水题,数据结构,算法学习,模拟,DP,动态规划-树形DP,模板,搜索-bfs)