第九周习题

A、最大字段和升级版

题目描述

  • 使用动态规划算法求整数数组(可能包含负整数)的最大子段和,以及和最大子段的起始位置和结束位置:
    例如:输入数组(6,-1,5,4,-7),输出14, 1,4,其中14表示最大子段和,1表示和最大的子段从第1个数字开始,4表示和最大的子段到第4个数字结束,即(6, -1 , 5, 4)。

输入

  • 每组输入两行,第1行为数组中包含的整数个数n,第2行为n个整数(可能包含负整数),两两之间用空格隔开。

输出

  • 输出最大子段和,以及和最大子段的起始位置和结束位置,两两之间用空格隔开。

样例输入 Copy

5
6 -1 5 4 -7

样例输出 Copy

14 1 4

【这个题目,直接贯穿了我的整个五一假期,还多加了几天的时间,其实大部分代码我都写好了,只有一个地方有问题,就是输入1,它只会输出1 0 0,不是输出1 1 1 ,然而就是这个问题困扰了我好久好久,然后就是,因为五一也出去完了,更加没思路了,好不容易问了室友才恍然大悟,就是我设置的起始位置和终止位置的初始化一直都是设置的0,改成1就行了,所以我那么久CSDN也没找到答案,哭了~我室友是直接在循环的过程记录起始位置的,所以直接调用输出就行,但是我懒得改了,放一个链接吧,对后面的题目有很大帮助哈:和我一样的题目~戳她戳她!

代码

import java.util.Scanner;

public class Main {
    
	public static int []a = new int[105];
	public static int []b = new int[105];
	public static int n,maxSum,index,maxIndex,max_S;
	
	public static void solve(){
		b[0] = a[0];
		maxSum = b[0];
		index = 1;
		maxIndex = 1;
		   
		for(int j=1;j<n;j++){
			   
			if(b[j-1]>0)
				b[j] = b[j-1]+a[j];
			else{
				b[j] = a[j];
				
			}
			   
			if(b[j]>maxSum){
				maxSum = b[j];
				maxIndex = j+1;
			}
			
		   max_S = maxSum;
 		   for(int i = maxIndex-1;i>=0;i--){
 			   max_S-=a[i];
 			   if(max_S==0)
 				   index = i+1;
 		   }
	}
}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
	   Scanner sc = new Scanner(System.in);
       while(sc.hasNext()){
    	   n = sc.nextInt();
    		   for(int i=0;i<n;i++)
        		   a[i] = sc.nextInt();
        	   solve();
        	   System.out.println(maxSum+" "+index+" "+maxIndex);
    	   }
    	   
   		   
       }
   }

B、斜线最大最小值

题目描述

  • 求如图所示一个上三角矩阵中每一条斜线中的最大元素(L)和最小元素(S)。
    在这里插入图片描述
    输入
  • 每组输入包括两部分,一部分为数字n,表示三角矩阵的行数。
  • 第二部分即为三角矩阵。

输出

  • 每一个对角线输出一行,每行包括Lx=Max,
    Sx=Min,其中x为斜线序号(序号从1开始),Max为该斜线上的最大值,Min为该斜线上的最小值。

样例输入 Copy

6
1 3 5 7 11 20
0 6 8 2 3 13
0 0 7 4 8 9
0 0 0 18 3 10
0 0 0 0 12 6
0 0 0 0 0 15

样例输出 Copy

L1=18, S1=1
L2=8, S2=3
L3=10, S3=2
L4=9, S4=3
L5=13, S5=11
L6=20, S6=20
【有问题的话就戳上面的那个链接吧~我就是根据那个来的】

代码

import java.util.Scanner;

public class Main {
	public static int a[][] = new int[105][105];
	public static int max,min;

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
			int n = sc.nextInt();
			
			max = 0;min = 0;
			for(int i=1;i<=n;i++)
				for(int j=1;j<=n;j++)
					a[i][j] = sc.nextInt();
			
			
			for(int r=1;r<=n;r++){
				max = a[1][r];
				min = a[1][r];
				
				for(int i=1;i<=n-r+1;i++){
					int j=r+i-1;
					
					if(max<a[i][j])//最大值
						max = a[i][j];
					
					else if(min>a[i][j])//最小值
						min = a[i][j];
				}
				
				System.out.println("L"+r+"="+max+", "+"S"+r+"="+min);
				
			}
				
		}

	}

}

C、矩阵连乘问题-备忘录法求最优值

题目描述

  • 使用备忘录法求解矩阵连乘问题,输出最少乘法次数。

输入

  • 每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。

输出

  • 矩阵连乘最优计算次数。

样例输入 Copy

7
30 35 15 5 10 20 25

样例输出 Copy

15125

代码

import java.util.Scanner;

public class Main {
	public static int m[][] = new int[105][105];
	public static int s[][] = new int[105][105];
	public static int p[] = new int[105];
	public static int n;
	
	public static int lookup(int i,int j){
		
		for(int k=0;k<n;k++)
			for(int t=0;t<n;t++)
				m[k][t] = 0;
		
		
		if(m[i][j]>0)
			return m[i][j];
		
		if(i==j)
			return 0;
		int u = lookup(i+1,j)+p[i-1]*p[i]*p[j];
		s[i][j] = i;
		for(int k = i+1;k<j;k++){
			int t = lookup(i,k)+lookup(k+1,j)+p[i-1]*p[k]*p[j];
			if(t<u){
				u = t;
				s[i][j] = k;
			}
			
		}
		m[i][j] = u;
		return u;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
			n = sc.nextInt();
			for(int i=0;i<n;i++)
				p[i] = sc.nextInt();
			System.out.println(lookup(1,n-1));
		}

	}

}

D、矩阵连乘问题-动态规划求最优值

题目描述

  • 使用动态规划算法求解矩阵连乘问题,输出最少乘法次数。

输入

  • 每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。

输出

  • 矩阵连乘最优计算次数。

样例输入 Copy

7
30 35 15 5 10 20 25

样例输出 Copy

15125

代码

import java.util.Scanner;

public class Main {
	
	public static int m[][] = new int[105][105];
	public static int s[][] = new int[105][105];
	public static int p[] = new int[105];
	public static int n;

	public static void matrixChain(int []p,int [][]m,int [][]s){
		
		for(int i=1;i<=n;i++)
			m[i][i] = 0;
		
		for(int r=2;r<=n;r++)
			for(int i=1;i<=n-r+1;i++){
				
				int j = i+r-1;
				m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];
				s[i][j] = i;
				
				for(int k = i+1;k<j;k++){
					
					int t = m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
					if(t<m[i][j]){
						m[i][j] = t;
						s[i][j] = k;
					}
				}
			}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
			n = sc.nextInt();
			for(int i=0;i<n;i++)
				p[i] = sc.nextInt();
			matrixChain(p,m,s);
			System.out.println(m[1][n-1]);
		}

	}

}

E、矩阵连乘问题-构造最优解

题目描述

  • 使用动态规划算法求解矩阵连乘问题。

输入

  • 每组数据包括两行,第一行为数组长度n,第二行为存储矩阵维数的一维数组。

输出

  • 矩阵连乘最优计算次序。

样例输入 Copy

7
30 35 15 5 10 20 25

样例输出 Copy

A[2:2] * A[3:3]
A[1:1] * A[2:3]
A[4:4] * A[5:5]
A[4:5] * A[6:6]
A[1:3] * A[4:6]

代码

import java.util.Scanner;

public class Main {
	
	public static int m[][] = new int[105][105];
	public static int s[][] = new int[105][105];
	public static int p[] = new int[105];
	public static int n;

	public static void matrixChain(int []p,int [][]m,int [][]s){
		
		for(int i=1;i<=n;i++)
			m[i][i] = 0;
		
		for(int r=2;r<=n;r++)
			for(int i=1;i<=n-r+1;i++){
				
				int j = i+r-1;
				m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];
				s[i][j] = i;
				
				for(int k = i+1;k<j;k++){
					
					int t = m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
					if(t<m[i][j]){
						m[i][j] = t;
						s[i][j] = k;
					}
				}
			}
	}
	
	public static void traceback(int [][]s,int i,int j){
		if(i==j)
			return;
		traceback(s,i,s[i][j]);
		int t = s[i][j]+1;
		traceback(s,t,j);
		System.out.println("A["+i+":"+s[i][j]+"] * "+"A["+t+":"+j+"]");
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
			n = sc.nextInt();
			for(int i=0;i<n;i++)
				p[i] = sc.nextInt();
			matrixChain(p,m,s);
			traceback(s,1,n-1);
			
		}

	}

}

F、石子合并问题

题目描述

  • 在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数。求把所有石子合并成一堆的最小花费。例如:输入{1,2,3,4,5},输出33。【3+6+9+15=33】

输入

  • 本题应该处理到文件尾,每组输入包括两行,第一行为石子堆的个数n,第二行则为每堆石子的个数。

输出

  • 输出最小花费。

样例输入 Copy

5
1 2 3 4 5

样例输出 Copy

33

代码

import java.util.Scanner;

public class Main {
	
	public static int m[][] = new int[105][105];
	public static int s[][] = new int[105][105];
	public static int p[] = new int[105];
	public static int n;

	public static void matrixChain(int []p,int [][]m,int [][]s){
		
		for(int i=1;i<=n;i++)
			m[i][i] = 0;
		
		for(int r=2;r<=n;r++)
			for(int i=1;i<=n-r+1;i++){
				
				int j = i+r-1;
				m[i][j] = m[i+1][j]+s[i][j];
				
				for(int k = i+1;k<j;k++){
					
					int t = m[i][k]+m[k+1][j]+s[i][j];
					if(t<m[i][j]){
						m[i][j] = t;
					}
				}
			}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		while(sc.hasNext()){
			n = sc.nextInt();
			for(int i=1;i<=n;i++)
				p[i] = sc.nextInt();
			
			for(int i=1;i<=n;i++)
				s[i][i] = p[i];
			
			for(int i=1;i<=n;i++)
				for(int j=i+1;j<=n;j++)
					s[i][j] = s[i][j-1]+p[j];
			matrixChain(p,m,s);
			System.out.println(m[1][n]);
		}

	}

}

【鉴于小编五一的时候学骑自行车摔伤了,所以就不和你们唠嗑了,小编虽然五一摔伤了,但是还是和室友出去玩了,去拍了很多照片,吃了臭豆腐,吃了炸鸡,吃了凉皮,吃了好多好多东西,O(∩_∩)O哈哈~,开心!】

句子君:
“但是啊,这世界上不是所有的事情都能如你所愿,有样东西必定会成为你成功的绊脚石,知道是什么吗?就是人的感情!无聊的嫉妒、傲慢、偏见、迷恋都是绊脚石,压制住这些感情,权衡眼前的利益取舍,这就是胜负的关键,只有成功才能开创人生道路,不管别人怎样把你当傻瓜,怎样被社会无视,只要拿出成果就会让人重新认识你,只要通过这一场考试,就能使生活环境发生巨变,被一时感情冲昏而损失利益的只能称之为傻瓜。”

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少年游四方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值