博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA算法:合并石子堆——JAVA版本算法(动态规划算法)
阅读量:4040 次
发布时间:2019-05-24

本文共 2266 字,大约阅读时间需要 7 分钟。

JAVA算法:合并石子堆——JAVA版本算法(动态规划算法)

在一个圆形操场的四周摆放着n堆石子(n<= 100),现要将石子有次序地合并成一堆。规定每次只能选取相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。

请编写算法,读入石子堆数n及每堆的石子数(<=20)。选择一种合并石子的方案,使得做n-1次合并,得分的总和最小。

例如:有4堆石子:4 4 5 9

则最佳合并方案如下:

4 4 5 9  score: 0
8 5 9     score: 8
13 9      score: 8 + 13 = 21
22         score: 8 + 13 + 22 = 43

输入信息

可能有多组测试数据。 当输入n=0 时,结束。

第一行为石子堆数 n (1<=n<=100);第二行为 n 堆的石子每堆的石子数,每两个数之间用一个空格分隔。

输出信息

合并的最小得分,每个结果一行。

问题解析

这个问题和直线型的区别在于最后一堆和第一堆也是相邻的,可以把圆形转换成直线型,把问题扩展为2n-1堆石子。

例如:如果环形石子堆是 4 4 5 9,那么转换成直线型就变成了 4 4 5 9 4 4 5,所以最终就不是计算  0~n-1了,而是在 0~n-1,1-n,2-n+1,...,n-1~2n-2中选择最小的。

计算方法和直线型的相同。

算法设计

package com.bean.algorithm.beginner;import java.util.Scanner;public class MergeStones {	private static int n;	private static int[] arr;	private static int[] sum;	private static int[][] dp;	/**	 * @param args	 */	public static void main(String[] args) {		// TODO Auto-generated method stub		Scanner sc = new Scanner(System.in);		n = sc.nextInt();		arr = new int[2 * n];		sum = new int[2 * n];		for (int i = 1; i <= n; i++) {			arr[i] = sc.nextInt();			sum[i] = sum[i - 1] + arr[i];		}		for (int i = n + 1; i <= 2 * n - 1; i++) {			arr[i] = arr[i - n];			sum[i] = sum[i - 1] + arr[i];		}		minFun();		maxFun();	}	private static void minFun() {		dp = new int[2 * n][2 * n];		for (int r = 1; r <= n - 1; r++) {			for (int i = 1; i <= 2 * n - 1; i++) {				int j = i + r;				if (j >= 2 * n) {					continue;				}				dp[i][j] = dp[i][i] + dp[i + 1][j] + sum[j] - sum[i - 1];				for (int k = i + 1; k < j; k++) {					dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]);				}			}		}		int result = dp[1][n];		for (int i = 2; i <= n; i++) {			result = Math.min(result, dp[i][n - 1 + i]);		}		System.out.println(result);	}	private static void maxFun() {		dp = new int[2 * n][2 * n];		for (int r = 1; r <= n - 1; r++) {			for (int i = 1; i <= 2 * n - 1; i++) {				int j = i + r;				if (j >= 2 * n) {					continue;				}				dp[i][j] = dp[i][i] + dp[i + 1][j] + sum[j] - sum[i - 1];				for (int k = i + 1; k < j; k++) {					dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[k + 1][j] + sum[j] - sum[i - 1]);				}			}		}		int result = dp[1][n];		for (int i = 2; i <= n; i++) {			result = Math.max(result, dp[i][n - 1 + i]);		}		System.out.println(result);	}}

程序运行结果:

输入信息:

4

4
4
5
9

输出结果;

43

54

 

转载地址:http://lntdi.baihongyu.com/

你可能感兴趣的文章
js正则表达式限制文本框只能输入数字,小数点,英文字母
查看>>
Spring事务失效的原因
查看>>
mybatis获取数据库表字段名+数据
查看>>
使用springfox整合SpringMVC和Swagger
查看>>
JAVA静态代理和动态代理
查看>>
使用Navicat计划任务备份mysql数据库
查看>>
Java高并发,如何解决,什么方式解决
查看>>
深入理解分布式事务,高并发下分布式事务的解决方案
查看>>
分布式事务一些总结与思考
查看>>
Spring Cloud微服务架构实践与经验总结
查看>>
Spring Boot入门篇
查看>>
spring cloud服务的注册与发现(Eureka)
查看>>
Java IO流
查看>>
多线程
查看>>
互联网产品设计:产品即服务
查看>>
UrlreWirte的使用
查看>>
使用js定位到页面某个位子
查看>>
java获取客户端真实ip
查看>>
SWFUPLOAD的使用(java版)
查看>>
Memcached的使用(基于java)
查看>>