PAT甲级1045 Favorite Color Stripe(JAVA版)

31 篇文章 0 订阅

本题考查

动态规划问题(LCS算法),因为题目要求元素可重复,所以判断赋值的状态方程与原始LCS有区别

动态规划介绍

  1. 动态规划的核心就是:根据之前已经解决的子问题的解来求解父问题,换句话说“先解决子问题,再由子问题解决父问题”
  2. 动态规划实例:《算法导论》钢管切割问题
  3. 详细的动态规划介绍可以参考https://blog.csdn.net/u013309870/article/details/75193592

LCS最长公共子序列问题介绍

从两个序列A与B中找到最长的子序列,如A<1,2,3,4,5,6>、B<3,5,6>,则AB最大的公共序列为<3,5,6>。
使用动态规划方法求解LCS最长公共子序列的核心就是理解下式:
来自https://blog.csdn.net/so_geili/article/details/53737001
解析:Xi为X序列中第i个元素,Yj为Y序列中第j个元素。两个序列的LCS问题包含两个序列的前缀的LCS,因此,LCS问题具有最优子结构性质。
设C[i,j]表示Xi和Yj的最长公共子序列LCS的长度。

  1. 如果i=0或j=0,即一个序列长度为0时,那么LCS的长度为0。
  2. 如果Xi = Yj,则代表C[ i,j ]等于先前的公共序列长度加1,先前的公共序列即C[i - 1,j - 1]
  3. 如果Xi ≠ Yj,则代表C[i,j]等于C[ i,j - 1]与C[i - 1,j ]两者中较大的一个

参考资料:

代码

最后一个用例超时,C++代码不会超时

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		int[][] dp = new int[205][10005];
		Scanner scaner = new Scanner(System.in);
		scaner.nextInt();
		int round1 = scaner.nextInt();
		int[] order = new int[round1];
		for(int i = 0 ; i < round1 ; i++) {
			order[i] = scaner.nextInt();
		}
		int round2 = scaner.nextInt();
		int[] color = new int[round2];
		for(int i = 0 ; i < round2 ; i++) {
			color[i] = scaner.nextInt();
		}
		scaner.close();
		for(int i = 1 ; i <= round1 ; i++) {
			for(int j = 1 ; j <= round2 ; j++) {
				if(order[i - 1] == color[j - 1])
					//元素不能重复版本
//					dp[i][j]=dp[i-1][j-1]+1;
				    //元素可以重复版本
					dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1])+1;
				else
					dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
					
			}
		}
		System.out.println(dp[round1][round2]);
	}
}

需要注意!!!
本题元素可重复,所以状态方程与原始LCS算法有区别
如果不能重复等于同一个元素

if (order[i] == color[j]) 
   dp[i][j] = dp[i-1][j-1] +1;
else 
   dp[i][j] = Math.max(dp[i][j-1] , dp[i-1][j])

如果可以重复等于

if (order[i] == color[j]) 
   dp[i][j] = max(dp[i-1][j] , dp[i][j-1]) +1;
else 
   dp[i][j] = Math.max (dp[i-1][j] ,dp[i][j-1])

参考:https://blog.csdn.net/Cute_jinx/article/details/81911913
最后把dp矩阵非零部分输出出来便于理解运行过程,该矩阵使用的用例是PAT标准用例1

6
5 2 3 1 5 6
12 2 2 4 1 5 5 6 3 1 1 5 6

//dp矩阵
1 2 2 2 2 2 2 2 2 2 2 2 
1 2 2 2 2 2 2 3 3 3 3 3 
1 2 2 3 3 3 3 3 4 5 5 5 
1 2 2 3 4 5 5 5 5 5 6 6 
1 2 2 3 4 5 6 6 6 6 6 7
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值