离散化 洛谷P1052 [NOIP2005 提高组] 过河

原题链接洛谷P1052 [NOIP2005 提高组] 过河
洛谷上一位大佬写得很好:Actinoi’s blog: 过河
我的AC代码:

#include <bits/stdc++.h>
#define maxl 1000000005
#define maxm 105
using namespace std;

int L;
int s, t, m;

int stone[maxm]; 
int bridge[110*110]; 
int dp[110*110];

/*
这题关键在于离散化
当两个石子之间的距离很远时,把中间的无相关的距离缩减掉
本题的规则:
当stone[i]和stone[i-1]的距离大于s*t时
将两者的距离缩减为(stone[i]-stone[i-1)%s+s*t

这里只看走s步的化(也可以走t步) 
如果上一个石子的位置记为0,则把stone[i]和stone[i-1]之间可以通过k*s到达的位置都消去了,留下了(stone[i]-stone[i-1]%t的距离,再加上一个从0一定可达的位置:s*t 
*/
int main(int argc, char *argv[]) {
	cin>>L;
	cin>>s>>t>>m;
	for(int i=0; i<m; i++){
		cin>>stone[i];	
	}
	sort(stone, stone+m);
	int identify = 0;
	/*
	这里我一开始犯了一个致命的错误,就是每次更改距离后,就把石子的坐标更改了,导致后续石子之间的距离发生改变。
	所以这里用identify暂存每次更改位置后的石子坐标,stone[]是一定不能改变的。
	*/
	if(stone[0] > s*t){
		identify += stone[0]%s+s*t;
	}
	else{
		identify += stone[0];
	}
	bridge[identify] = 1;
	for(int i=1; i<m; i++){
		if(stone[i]-stone[i-1]>s*t){//离散化处理 
			identify += (stone[i]-stone[i-1])%s+s*t;
		}
		else{
			identify += stone[i]-stone[i-1];
		}
		bridge[identify] = 1;
	}
	/*
	for(int i=0; i<=10; i++){
		cout<<bridge[i]<<' ';
	}
	cout<<endl;
	*/
	if(L-stone[m-1] > s*t){
		L = identify + (L-stone[m-1])%s+s*t;
	}
	else{
		L = identify + L-stone[m-1];
	}
	//memset(dp, 0, sizeof(dp));
	//dp[0] = 0;
	for(int i=1; i<s; i++){
		dp[i] = 1e9;
	}
	for(int i=s; i<=L-1+t; i++){
		dp[i] = 1e9;
		for(int j=i-t; j<=i-s; j++){
			if(j >= 0)
				dp[i] = min(dp[i], dp[j]+bridge[i]);
		}
		//cout<<dp[i]<<' ';
	}
	//cout<<endl;
	int res = 1e9;
	for(int i=L; i<=L-1+t; i++){
		res = min(res, dp[i]);
	}
	cout<<res<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值