P1052 过河 题解

本文介绍了一种使用一维动态规划解决桥梁建设问题的方法。考虑到桥的长度可能非常大,采用离散化处理来优化计算过程。通过具体实例展示了如何设定状态转移方程,并给出完整的代码实现。

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

题目入口 洛谷
!!!dp数组开大了 初始化为1e9,然后一直报错,案例都过不了,对题解也没错,前后浪费好几小时。
由于桥的长度为 L(1 <= L <= 1e9),所以需要对坐标进行离散化,离散后最坏的长度 2000,这时候可以进行 一维动态规划。
状态转移方程:
dp[ i ] = min( dp[i - j] + v[ i ], dp[ i ] ) i >= j

注意:
在这里插入图片描述
当事人很后悔没注意看题,所以终点是一个范围不是一个点

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
int l, s, t, m;
int dp[2*maxn], v[2*maxn], f[maxn];
int main(){
	cin >> l;
	cin >> s >> t >> m;
	
	memset(dp , 105,sizeof(dp));
	memset(v, 0, sizeof(v));
	
	for(int i = 1; i <= m; i++){
		cin >> f[i];
	}
	f[0] = 0, f[m + 1] = l;
	sort(f, f + m + 2);
	
	// 坐标离散化
	int cnt = 0;	
	for(int i = 1; i <= m + 1; i++){
		if(f[i] - f[i - 1] >= t)
			cnt += (f[i] - f[i - 1]) % t + t;
		else
			cnt += f[i] -f[i - 1];
		v[cnt] = 1;
	}	
	v[cnt] = 0, v[0] = 0;
	
	// 动态规划
	dp[0] = 0;
	for(int i = 1; i <= cnt + t - 1; i++){
		for(int j = s; j <= t; j++){
			if( i >= j)
				dp[i] = min(dp[i - j] + v[i], dp[i]);
		}
	}
	
	// 找出最小值
	int ans = 2e9;
	for(int i = cnt; i <= cnt + t - 1; i++)
		ans = min(ans, dp[i]);
	cout << ans << endl;
	
	return 0;
}
过河卒是一个典型的动态规划问题。首先,我们将整个棋盘看作一个二维数组,数组的每个元素表示到达该位置的路径数目。然后,我们根据题目给出的条件,逐步更新数组中的元素,直到计算出到达目标位置的路径数目。 具体的解题思路如下: 1. 首先,我们可以将马的位置设置为0,表示无法经过该位置。 2. 然后,我们根据马的位置,更新数组中的元素。对于二维数组中的每个位置,我们根据左边和上边的位置来计算到达当前位置的路径数目。具体地,如果左边和上边的位置都可以经过,那么到达当前位置的路径数目就等于左边和上边位置的路径数目之和。如果左边或上边的位置无法经过,那么到达当前位置的路径数目就等于左边或上边位置的路径数目。 3. 最后,我们输出目标位置的路径数目。 下面是洛谷p1002过河题解的C++代码: ```cpp #include <bits/stdc++.h> using namespace std; int main() { long long a[21][21]; int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; // 初始化数组,马的位置设置为0 for(int i=0; i<=20; i++) { for(int k=0; k<=20; k++) { a[i][k] = 1; } } a[x2][y2] = 0; // 根据马的位置更新数组中的元素 if(x2 >= 2 && y2 >= 1) a[x2-2][y2-1] = 0; if(x2 >= 1 && y2 >= 2) a[x2-1][y2-2] = 0; if(x2 <= 18 && y2 >= 1) a[x2+2][y2-1] = 0; if(x2 <= 19 && y2 >= 2) a[x2+1][y2-2] = 0; if(x2 >= 2) a[x2-2][y2+1] = 0; if(x2 >= 1) a[x2-1][y2+2] = 0; if(y2 >= 1) a[x2+2][y2-1] = 0; if(y2 >= 2) a[x2+1][y2-2] = 0; // 动态规划计算路径数目 for(int i=1; i<=20; i++) { for(int k=1; k<=20; k++) { if(a[i][k] != 0) { a[i][k] = a[i-1][k] + a[i][k-1]; } } } // 输出目标位置的路径数目 cout << a[x1][y1] << endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值