动态规划专题(明天继续)

动态规划求最大值:

题目描述

小蓝在一个 nn 行 mm 列的方格图中玩一个游戏。

开始时,小蓝站在方格图的左上角,即第 11 行第 11 列。

小蓝可以在方格图上走动,走动时,如果当前在第 rr 行第 cc 列,他不能走到行号比 rr 小的行,也不能走到列号比 cc 小的列。同时,他一步走的直线距离不超过 33。

例如,如果当前小蓝在第 33 行第 55 列,他下一步可以走到第 33 行第 66 列、第 33 行第 77 列、第 33 行第 88 列、第 44 行第 55 列、第 44 行第 66 列、第 44 行第 77 列、第 55 行第 55 列、第 55 行第 66 列、第 66 行第 55 列之一。

小蓝最终要走到第 nn 行第 mm 列。

在图中,有的位置有奖励,走上去即可获得,有的位置有惩罚,走上去就要接受惩罚。奖励和惩罚最终抽象成一个权值,奖励为正,惩罚为负。

小蓝希望,从第 11 行第 11 列走到第 nn 行第 mm 列后,总的权值和最大。请问最大是多少?

输入描述

输入的第一行包含两个整数 n,mn,m,表示图的大小。

接下来 nn 行,每行 mm 个整数,表示方格图中每个点的权值。

其中,1≤n≤100,−104≤权值≤1041≤n≤100,−104≤权值≤104。

输出描述

输出一个整数,表示最大权值和。

输入输出样例

示例 1

输入

3 5
-4 -5 -10 -3 1
7 5 -9 3 -10
10 -2 6 -10 -4

输出

15

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

实现:

import java.util.Scanner;
public class jump {
	 public static void main(String[] args) {
	        Scanner scan = new Scanner(System.in);
	        int n=scan.nextInt();
	        int m=scan.nextInt();
	        int[][] arr=new int[n][m];
	        for(int i=0;i0) {
	        			if(i-c>=0) {
	        				b[i][j]=Math.max(b[i][j], b[i-c][j]+arr[i][j]);
	        			}
	        			if(j-c>=0) {
	        				b[i][j]=Math.max(b[i][j], b[i][j-c]+arr[i][j]);
	        			}
	        			c--;
	        		}
	        	}
	        }
	        System.out.println(b[n-1][m-1]);
	    }
}

动态规划求最长子序列

题目描述

L 星球上的生物由蛋蓝质组成,每一种蛋蓝质由一类称为蓝肽的物资首尾连接成一条长链后折叠而成。

生物学家小乔正在研究 L 星球上的蛋蓝质。她拿到两个蛋蓝质的蓝肽序列,想通过这两条蓝肽序列的共同特点来分析两种蛋蓝质的相似性。

具体的,一个蓝肽可以使用 11 至 55 个英文字母表示,其中第一个字母大写,后面的字母小写。一个蛋蓝质的蓝肽序列可以用蓝肽的表示顺序拼接而成。

在一条蓝肽序列中,如果选取其中的一些位置,把这些位置的蓝肽取出,并按照它们在原序列中的位置摆放,则称为这条蓝肽的一个子序列。蓝肽的子序列不一定在原序列中是连续的,中间可能间隔着一些未被取出的蓝肽。

如果第一条蓝肽序列可以取出一个子序列与第二条蓝肽序列中取出的某个子序列相等,则称为一个公共蓝肽子序列。

给定两条蓝肽序列,找出他们最长的那个公共蓝肽子序列的长度。

输入描述

输入两行,每行包含一个字符串,表示一个蓝肽序列。字符串中间没有空格等分隔字符。

其中有 ,两个字符串的长度均不超过 10001000。

输出描述

输出一个整数,表示最长的那个公共蓝肽子序列的长度。

输入输出样例

示例

输入

LanQiaoBei
LanTaiXiaoQiao

输出

2

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M
import java.util.*;
public class lantai {
	 public static void main(String[] args) {
	        Scanner scan = new Scanner(System.in);
	        //在此输入您的代码...
	        String str1=scan.nextLine();
	        String str2=scan.nextLine();
	        scan.close();
	        int[] flag1=new int[str1.length()];
	        int[] flag2=new int[str2.length()];
	        int c=0;
	        int m=0,n=0;
	        for(int i=0;i='A'&&str1.charAt(i)<='Z') {
	        		flag1[c]=i;
	        		c++;
	        		m++;
	        	}
	        }
	        flag1[c]=str1.length();
	        c=0;
	        for(int i=0;i='A'&&str2.charAt(i)<='Z') {
	        		flag2[c]=i;
	        		c++;
	        		n++;
	        	}
	        }
	        flag2[c]=str2.length();
	        int[][] dp=new int[m+1][n+1];
	        for(int i=0;i

上述有两例发生段错误,

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
     public static void main(String[] args) {
	        Scanner scan = new Scanner(System.in);
	        //在此输入您的代码...
	        String str1=scan.nextLine();
	        String str2=scan.nextLine();
	        scan.close();
	        int[] flag1=new int[str1.length()+1];
	        int[] flag2=new int[str2.length()+1];
	        int c=0;
	        int m=0,n=0;
	        for(int i=0;i='A'&&str1.charAt(i)<='Z') {
	        		flag1[c]=i;
	        		c++;
	        		m++;
	        	}
	        }
	        flag1[c]=str1.length();
	        c=0;
	        for(int i=0;i='A'&&str2.charAt(i)<='Z') {
	        		flag2[c]=i;
	        		c++;
	        		n++;
	        	}
	        }
	        flag2[c]=str2.length();
	        int[][] dp=new int[m+1][n+1];
	        for(int i=1;i<=m;i++) {
	        	for(int j=1;j<=n;j++) {
//	        		System.out.println(str1.substring(flag1[i-1], flag1[i])+"  "+str2.substring(flag2[j-1], flag2[j]));
	        		if(str1.substring(flag1[i-1], flag1[i]).equals(str2.substring(flag2[j-1], flag2[j]))) {
	        			dp[i][j]=Math.max(dp[i][j], dp[i-1][j-1]+1);
	        		}else{
	        			dp[i][j]=Math.max(dp[i-1][j], dp[i][j-1]);
	        		}
	        	}
	        }

	        System.out.println(dp[m][n]);
	    }
}

包子凑数:

题目描述

小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有 NN 种蒸笼,其中第 ii 种蒸笼恰好能放 AiAi​ 个包子。每种蒸笼都有非常多笼,可以认为是无限笼。

每当有顾客想买 XX 个包子,卖包子的大叔就会迅速选出若干笼包子来,使得这若干笼中恰好一共有 XX 个包子。比如一共有 3 种蒸笼,分别能放 3、4 和 5 个包子。当顾客想买 11 个包子时,大叔就会选 2 笼 3 个的再加 1 笼 5 个的(也可能选出 1 笼 3 个的再加 2 笼 4 个的)。

当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有 3 种蒸笼,分别能放 4、5 和 6 个包子。而顾客想买 7 个包子时,大叔就凑不出来了。

小明想知道一共有多少种数目是包子大叔凑不出来的。

输入描述

第一行包含一个整数 NN (1≤N≤1001≤N≤100)。

以下 N 行每行包含一个整数 AiAi​ (1≤Ai≤1001≤Ai​≤100)。

输出描述

一个整数代表答案。如果凑不出的数目有无限多个,输出 INF。

输入输出样例

示例 1

输入

2
4
5

输出

6

样例说明

凑不出的数目包括:1, 2, 3, 6, 7, 11。

示例 2

输入

2
4
6

输出

INF

样例说明

所有奇数都凑不出来,所以有无限多个

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M
import java.util.*;
public class baozicoushu {
	 public  static  int  gcd(int a,int b) {
			if(b==0) {
				return a;
			}else {
				return gcd(b,a%b);
			}
		}
		 public static void main(String[] args) {
			 Scanner scan = new Scanner(System.in);
		     int n=scan.nextInt();
		     int[] a=new int[n+1];
		     int s;
		     for(int i=1;i<=n;i++) {
		    	 a[i]=scan.nextInt();
		     }
		     scan.close();
		     s=a[1];
		     for(int i=1;i<=n;i++) {
		    	 s=gcd(s,a[i]);      //求得最大公约数(所输入每一笼包子数的最大公约数)
		     }
	       if(s!=1) {			//这些数中包含最大公约数,不互质,例如3,6,9这些数不能组成的数为无穷
		    	 System.out.println("INF");
		     }else{
	         boolean[] f=new boolean[10001];
		     f[0]=true;
		     for(int i=1;i<=n;i++) {
		    	 for(int j=0;j<10001;j++) {	//标记数组,寻找不能凑成的数字
		    		 if(f[j]&&(j+a[i])<10001) {
		    			 f[j+a[i]]=true;
		    		 }
		    	 }
		     }
		     int sum=0;
		     for(int i=1;i<10001;i++) {
		    	 if(!f[i]) {
		    		 sum++;
		    	 }
		     }
		     System.out.println(sum);
	       }
		     
		 }
}

你可能感兴趣的:(动态规划,算法,数据结构)