sdnu 1087.过河(NOIP 2005 提高组)DP状态压缩

本文探讨了如何使用动态规划解决石子跳跃问题,通过定义状态转移方程和进行状态压缩,实现了对复杂情况的有效求解。具体而言,文章首先分析了问题背景,然后介绍了动态规划的基本思路,并通过实例演示了算法的具体实现过程。

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

原题链接:http://210.44.14.31/problem/show/1087


假设s=4,t=5


有图易知,在s*t后的位置都可到达。

因此,我们可以将无石子长度大于s*t的部分压缩为 s*t 。


状态转移方程:

F[ i ]=min( F[ i ] , F[ j ] )

j的范围:  i - T<= j <= i-S


代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
int main()
{
	int L,S,T,M;
	int stone[100 + 5];		//记录原来石子的位置
	int stonepos[10000 + 10];		//记录压缩后石子的位置
	int f[10000 + 10];	//dp
	int ans = 200;
	memset(stonepos, 0, sizeof(stonepos));
	cin >> L >> S >> T >> M;
	for (int i = 1; i <= M; i++)
		cin >> stone[i];
	if (S != T)
	{
		sort(stone + 1, stone + M + 1);
		stone[0] = 0;
		int dis, pos = 0;	//dia记录相邻两点的距离  pos表示已经处理到位置
		for (int i = 1; i <= M; i++)
		{
			dis = stone[i] - stone[i - 1];
				if (dis<=S*T)		//小于压缩值时,按原值处理
					pos += dis;
				else
					pos += T*S;
			stonepos[pos] ++;	//有石子的位置
		}
		f[0] = 0;
		for (int i = 1; i < pos + T; i++)	//pos+T 而不是L    很好理解!
		{
			f[i] = 200;
			for (int j = i - T; j <= i - S; j++)		//能跳到 i 点前的最小值
			if (j >= 0)
				f[i] = min(f[j], f[i]);
			f[i] += stonepos[i];		//再加上该点石子的数量
			if (i > pos)	//找跳过最后一个石子 所踩石子最小的值。
				ans = min(f[i], ans);
		}
	}
	else		//S==T时
	{
		ans = 0;
		for (int i = 1; i <= M;i++)
		if (stone[i] % S == 0)
			ans++;
	}
	cout << ans ;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值