2023-08-30力扣每日一题

链接:

1654. 到家的最少跳跃次数

题意:

从0出发,到X的最少步数

  • 它可以 往前 跳恰好 a 个位置(即往右跳)。
  • 它可以 往后 跳恰好 b 个位置(即往左跳)。
  • 它不能 连续 往后跳 2 次。
  • 它不能跳到任何 forbidden 数组中的位置。

解:

乐了,这下真成傻子了

两个判断条件我把有continue的放前面了

基本的DFS+DP,要注意一下几个点

  • 分成两个数组,一个装加减都可以的,一个装只能加的,vector,unordered_set都行

  • 找加减都能走的时候,条件是dp[i+a]>=dp[i]+1而不是dp[i+a]>dp[i]+1,因为即使dp[i+a]==dp[i]+1时,有可能那一步是通过某个数减到达的,那么这个数只经过了加,而我们找加减都行就要算上他

  • 对于找只能加的就很好判断了dp[i-b]>dp[i]+1,因为这个数如果之前出现过,如果是加来的,它就经过了加减,如果是减来的,它就经过了加,总之它在这一步之前就计算过了加的结果,就不用再算了

  • 上界没超过6000,这个看评论区推的,我还以为4001

  • 先算只能加的那个数组更快,原理不想想了

  • 贴个数据

  • vector/先加/后加减

    • 2023-08-30力扣每日一题_第1张图片
  • vector/先加减/后加

    • 2023-08-30力扣每日一题_第2张图片
  • unordered_set/先加/后加减

    • 2023-08-30力扣每日一题_第3张图片
  • unordered_set/先加减/后加

    • 2023-08-30力扣每日一题_第4张图片

实际代码:

#include
using namespace std;
static constexpr int Max=1E5+7;
int minimumJumps(vector& forbidden, int a, int b, int x)
{
	mapbook;
	for(auto i:forbidden) book[i]=true;
	
	vectordp(Max,INT_MAX-1);dp[0]=0;
	vectorstart{0},noBack;//unordered_set 
	while(true)
	{
		vectornext,nextNoBack;//unordered_set
		//加 
		for(auto i:noBack)
		{
			if(book.find(i+a)!=book.end() || i+a>6001 || dp[i+a]=0 && dp[i-b]>dp[i]+1)
			{
				dp[i-b]=dp[i]+1;
				nextNoBack.push_back(i-b);
			}
			if(book.find(i+a)!=book.end() || i+a>6001 || dp[i+a] forbidden;int a,b,x,temp;
	cin>>a>>b>>x;
	while(cin>>temp) forbidden.push_back(temp);
	int ans=minimumJumps(forbidden,a,b,x);
	cout<

限制:

  • 1 <= forbidden.length <= 1000
  • 1 <= a, b, forbidden[i] <= 2000
  • 0 <= x <= 2000
  • forbidden 中所有位置互不相同。
  • 位置 x 不在 forbidden 中。

你可能感兴趣的:(力扣每日一题,leetcode)