最短最优升级路径

博客围绕游戏补丁升级问题,玩家需升级到最新版且下载量最小。给出输入输出样例,分析采用动态规划思想,通过公式dp[j]=min(dp[j],dp[i]+size)求最小下载量,还介绍了反向推导最短升级路径的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:游戏网站提供若干升级补丁,每个补丁大小不一,玩家要升级到最新版,如何选择下载哪些补丁下载量最小。

输入:

第一个数为用户版本  第二个数为最新版本,空格分开

接着输入N行补丁数据        第一个数补丁开始版本 第二个数为补丁结束版本 第三个数为补丁大小,空格分开

 

样例输入

1000 1050

1000 1020 50

1000 1030 70

1020 1030 15

1020 1040 30

1030 1050 40

1040 1050 20

输出

对于每个测试实例,输出一个升级路径以及最后实际升级的大小

样例输出

1000->1020->1040->1050(100)

 

分析:求最小下载量,可以使用dp思想,dp[j]=min(dp[j],dp[i]+size),其中i为补丁开始版本,j为补丁结束版本,size为补丁大小,最后直接取dp中最新版本的位置即为最小下载大小

要求同时输出最短升级路径,这里在求出dp之后反向推导升级路径,即对于每行输入,当dp[i]=dp[j]-size时,i即为升级路径,因为升级路径可能不止一条,所以从头开始遍历,即两重for循环,第一层从最新版本向前推导,第二层从头向后寻找最少的升级路径

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;



public class Main {

	static int[] flag;
	static ArrayList<int[]> al;
	static int min = Integer.MAX_VALUE;

	public static void main(String[] args) {

		Scanner in = new Scanner(System.in);
		al = new ArrayList<int[]>();

		int star = in.nextInt();
		int end = in.nextInt() - star;
		int max = 0;
		//因为没有标注N为多少,只能用hasnext来判断是否输入结束
		while(in.hasNext()) {
			int[] te = new int[3];
			te[0] = in.nextInt() - star;
			te[1] = in.nextInt() - star;
			te[2] = in.nextInt();
			al.add(te);
			max = Math.max(max, te[1]);
		}
		int len = al.size();
		flag = new int[max + 1];
		Arrays.fill(flag, Integer.MAX_VALUE);
		
		fun();
		ArrayList<Integer> al1=fun1(max);
		StringBuilder sb =new StringBuilder();
		for(int i=al1.size()-1;i>=0;i--) {
			int num=al1.get(i);
			sb.append(num+1000+"->");
		}
		sb.delete(sb.length()-2, sb.length());
		sb.append("("+flag[max]+")");
		System.out.println(sb.toString());
	}

	public static void fun() {

		for (int i = 0; i < al.size(); i++) {

			int[] temp = al.get(i);
			if (temp[0] == 0) {
				flag[temp[1]] = temp[2];
			} else {
				flag[temp[1]] = Math.min(flag[temp[0]] + temp[2], flag[temp[1]]);
			
			}

		}
	}

	static ArrayList<Integer> fun1(int end) {
		ArrayList<Integer> al1=new ArrayList<Integer>();
		al1.add(end);
		int end1=end;
		for(int i=al.size()-1;i>=0;i--) {
			for(int j=0;j<al.size();j++) {
				int[] temp = al.get(j);
				if(temp[1]==end1) {
					if(flag[temp[0]]==flag[end1]-temp[2]) {
						end1=temp[0];
					al1.add(end1);
					break;
					}
					
				}
			}
			
		}
		al1.add(0);
		return al1;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值