1. 程式人生 > 資訊 >特斯拉再次推遲 Model S/X 在美預期交付時間:延期至 2022 年 3 月至 4 月

特斯拉再次推遲 Model S/X 在美預期交付時間:延期至 2022 年 3 月至 4 月

洛谷 P1156 垃圾陷阱

原題連結

Solution

演算法:揹包

看似毫無關係,下面我們來分析一下。

把深度 \(D\) 看作揹包容量,每個垃圾堆放高度 \(h\) 看作物體體積,增加生命長度 \(l\) 看作物體價值。

這不就是一個揹包了嘛。

定義 \(f[i][j]\) 表示到第 \(i\) 個垃圾,高度為 \(j\) 時擁有的最長生命時間。

轉移方程

\(i\) 個垃圾用於增加生命:\(f[i][j] = max(f[i][j], f[i - 1][j] + a[i].l - (a[i].t - a[i - 1].t)\)

\(i\) 個垃圾用於搭高: \(f[i][j] = max(f[i][j], f[i - 1][j - a[i].h] - (a[i].t - a[i - 1].t)\)

這個 \(f\) 第一維也是可以用滾動陣列消掉的。

看程式碼理解吧

完整程式碼

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 1010;
struct node{
	int t, l, h;
}a[N];
int m, n;
int f[2][N];		//前i個垃圾,到高度j擁有的最長生命時間(滾動)

bool cmp(node x, node y){
	return x.t < y.t;
}

int main(){
	scanf("%d%d", &m, &n);
	for(int i = 1; i <= n; i++)
		scanf("%d%d%d", &a[i].t, &a[i].l, &a[i].h);
	sort(a + 1, a + 1 + n, cmp);
	f[0][0] = 10;
	int ans = 10;									//注意初值等於10
	for(int i = 1; i <= n; i++){
		int lin = i & 1, pre = lin ^ 1;				//滾動,自己理解一下
		memset(f[lin], 128, sizeof(f[lin]));		//注意要不停的賦初始值
		for(int j = m; j >= 0; j--){
			if(f[pre][j] < a[i].t - a[i - 1].t) continue;
			if(j + a[i].h >= m){					//高度>=m 就輸出
				printf("%d\n", a[i].t);
				return 0;
			}
			f[lin][j + a[i].h] = max(f[lin][j + a[i].h], f[pre][j] - (a[i].t - a[i - 1].t));	//轉移
			f[lin][j] = max(f[lin][j], f[pre][j] + a[i].l - (a[i].t - a[i - 1].t));
		}
		ans = max(ans, f[lin][0] + a[i].t);			//不能出去的話,最長生命長度(高度為0)
	}
	printf("%d\n", ans);
	return 0;
}

End