DP Contest

A - Frog 1

发现 \(f[i]\) 只能从 \(f[i - 1], f[i - 2]\) 跳过来。

所以转移方程为 \(f[i] = min(f[i - 1] + abs(h[i] - h[i - 1], f[i - 2] + abs(h[i] - h[i - 2]) )\)

注意初始化 \(f[1] = 0, f[2] = abs(h[2] - h[1]])\)

int f[N], h[N], k;

signed main() 
{
	int n = read();
	for(int i = 1; i <= n; i++) h[i] = read();
	f[1] = 0, f[2] = abs(h[2] - h[1]);
	for(int i = 3; i <= n; i++) {
		f[i] = min(f[i - 1] + abs(h[i] - h[i - 1]), f[i - 2] + abs(h[i] - h[i - 2]));
	}
	cout << f[n];
	return 0;
}

B - Frog 2

这次这次青蛙可以一次跳 \([1, k]\) 里面的任意一步。

转移方程为 \(f[i] = min(f[i], f[i - j] + abs(h[i] - h[i - j]))1 \le j \le k \& i - j > 0\)

注意一开始赋极大值。

signed main() 
{
	n = read(), k = read();
	for(int i = 1; i <= n; i++) a[i] = read();
	memset(f, 63, sizeof f);
	f[1] = 0;
	for(int i = 2; i <= n; i++) {
		for(int j = 1; j <= k; j++) {
			if(i - j >= 1) f[i] = min(f[i], f[i - j] + abs(a[i] - a[i - j]));
		}
	}	
	cout << f[n];
	return 0;
}

C - Vacation

不能连续两天选重复的。

我们设 \(dp[i][j]\) 表示第 \(i\) 天选了第 \(a[i][j]\)

我们如何知道两天不能选重复的?

我们这两天的状态都枚举即可。

转移方程为 $ if(j \ne k) dp[i][j] = max(dp[i][j], dp[i - 1][k] + a[i][j]) $

int a[N][5];
int dp[N][5];

signed main() 
{
	int n = read();
	for(int i = 1; i <= n; i++) 
		for(int j = 1; j <= 3; j++)
			a[i][j] = read();	
	for(int i = 1; i <= 3; i++) dp[1][i] = a[1][i];
	for(int i = 2; i <= n; i++) {
		for(int j = 1; j <= 3; j++) {
			for(int k = 1; k <= 3; k++) {
				if(j != k) dp[i][j] = max(dp[i][j], dp[i - 1][k] + a[i][j]);
			}
		}
	}
	cout << max(dp[n][1], max(dp[n][2], dp[n][3]));
	return 0;
}

D - Knapsack 1

\(01\) 背包的板子题。

int n, V;
ll w[N], val[N], dp[N];

signed main() 
{
	n = read(), V = read();
	for(int i = 1; i <= n; i++) w[i] = read(), val[i] = read();
	for(int i = 1; i <= n; i++) {
		for(int j = V; j >= w[i]; j--) {
			dp[j] = max(dp[j], dp[j - w[i]] + val[i]);
		}
	}
	cout << dp[V];
	return 0;
}
posted @ 2022-07-12 05:57  TLE_Automation  阅读(11)  评论(0编辑  收藏  举报