【图论】C_算竞_升降梯上(二维抽象一维)

一、题目描述

开启了升降梯的动力之后,探险队员们进入了升降梯运行的那条竖直的隧道,映入眼帘的是一条直通塔顶的轨道、一辆停在轨道底部的电梯、和电梯内一杆控制电梯升降的巨大手柄。

Nescafé 之塔一共有 N 层,升降梯在每层都有一个停靠点。

手柄有 M 个控制槽,第 i 个控制槽旁边标着一个数Ci,满足C1<C2<C3<…<CM。

如果 Ci>0,表示手柄扳动到该槽时,电梯将上升 Ci 层;如果 Ci<0,表示手柄扳动到该槽时,电梯将下降 −Ci 层;并且一定存在一个 Ci=0,手柄最初就位于此槽中。

注意升降梯只能在 1~N 层间移动,因此扳动到使升降梯移动到 1 层以下、N 层以上的控制槽是不允许的。

电梯每移动一层,需要花费 2 秒钟时间,而手柄从一个控制槽扳到相邻的槽,需要花费 1 秒钟时间。

探险队员现在在 1 层,并且想尽快到达 N 层,他们想知道从 1 层到 N 层至少需要多长时间?

输入格式

第一行两个正整数 N、M。
第二行 M 个整数C1、C2…CM。

输出格式

输出一个整数表示答案,即至少需要多长时间。
若不可能到达输出-1。

数据范围

1≤N≤1000,
2≤M≤20,
−N<C1<C2<…<CM<N

输入样例:
6 3
-1 0 2
输出样例:
19

样例解释

手柄从第二个槽扳到第三个槽(0 扳到2),用时1 秒,电梯上升到3 层,用时4 秒。
手柄在第三个槽不动,电梯再上升到5 层,用时4 秒。
手柄扳动到第一个槽(2 扳到-1),用时2 秒,电梯下降到4 层,用时2 秒。
手柄扳动到第三个槽(-1 扳倒2),用时2 秒,电梯上升到6 层,用时4 秒。
总用时为(1+4)+4+(2+2)+(2+4)=19 秒。

二、题解

方法一:考建图

第一眼像是的 dp 啊,是的 dp 可以做,一个比较新颖的思路就是把问题转化为图论最短路问题:

  • 结点 1 为源点,n 为终点。
  • C [ i ] C[i] 原义为将电梯将移动 C i C_i 层,而在本算法中我将其表示为有向边的边权。
  • 每个控制槽 C [ i ] C[i] 代表不同的有向边,每一层电梯则为图中一个个的结点。
  • 由于边权可能为负,因此可能存在无穷循环移动的情况。
  • 至此,本问题可简化为求从 1 号点到 n 号点的最少时间花费。
import java.util.*;
import java.math.*;
import java.io.*;
public class Main{
	static int n, m; 
	static int[] C;
	static int[][] dist;
	static int INF = 0x3f3f3f3f;
	
	static void spfa(int S) {
	    for (int i = 1; i <= n; i++)
	    for (int j = 1; j <= m; j++) {
	        dist[i][j] = INF;
	    }
		Queue<Node> q = new ArrayDeque<>();
		boolean[][] inq = new boolean[n+1][m+1];
		q.add(new Node(1, S));
		inq[1][S] = true;
		dist[1][S] = 0;
		
		while (!q.isEmpty()) {
			Node t = q.poll();
			int f = t.f, s = t.s;
			inq[f][s] = false;
			for (int i = 1; i <= m; i++) {
				int tf = f + C[i];
				if (tf < 1 || tf > n)
					continue;
				if (dist[tf][i] > dist[f][s] + Math.abs(f-tf)*2 + Math.abs(s-i)) {
					dist[tf][i] = dist[f][s] + Math.abs(f-tf)*2 + Math.abs(s-i);
					if (!inq[tf][i]) {
						q.add(new Node(tf, i));
						inq[tf][i] = true;
					}
				}
			}
		}
	}
    public static void main(String[] args) throws IOException {  
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        BufferedWriter w = new BufferedWriter(new OutputStreamWriter(System.out));
        n = sc.nextInt();
		m = sc.nextInt();
		C = new int[m+1];
		
		int start = 0;
		for (int i = 1; i <= m; i++) {
			C[i] = sc.nextInt();
			if (C[i] == 0)
				start = i;
		}
		int min = INF;
		dist = new int[n+1][m+1];
		spfa(start);
		for (int i = 1; i <= m; i++) {
			min = Math.min(min, dist[n][i]);
		}
		System.out.println(min == INF ? -1 : min);
    }
	static class Node {
		int f, s;
		Node(int f, int s) {
			this.f = f;
			this.s = s;
		}
	}
}

复杂度分析

  • 时间复杂度: O ( k m ) O(km)
  • 空间复杂度: O ( . . . ) O(...)

方法二:dp

代办…


复杂度分析

  • 时间复杂度: O ( ) O()
  • 空间复杂度: O ( ) O()
发布了714 篇原创文章 · 获赞 199 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_43539599/article/details/105589208