在不使用图形的情况下,以最小的乘积从第一个索引到最后一个索引

Reaching from first index to last with minimum product without using Graphs?

本文关键字:索引 第一个 最后一个 图形 情况下      更新时间:2023-10-16

在编解码上解决这个问题:

在拜访了一个儿时的朋友后,大厨想回到他的家。朋友住在第一条街,大厨自己住在第n街(最后一条)街。他们的城市有点特别:你可以从那里搬走从X街到Y街当且仅当1 <= Y- X <= K,其中K是给定的整数值。大厨想要以这样一种方式回家,所有参观过的街道的产物特殊号码是最少的(包括第1街和第n街)。请帮他找到这样的产品。输入

第一行输入由两个整数N和K组成分别为街道数和K值。第二行由N个数字组成- A1, A2,…分别为AN,其中Ai等于到第i街的特殊号码。输出

请输出最小可能积的值,取模1000000007. 约束

1≤N≤10^5 1≤Ai≤10^5 1≤K≤N示例

输入:4 2 1 2 3 4.

输出:8

可以根据本教程使用图形来解决我试图解决它不使用图,只是使用递归DP。我的方法:

  1. 取一个数组,计算到达每个索引的最小积,并将其存储在相应的索引中。
  2. 可以使用自顶向下的方法,递归地发送索引(合格),直到到达起始索引。
  3. 在所有计算值中存储最小值。
  4. 如果它已经计算过,返回它,否则计算。
代码:

 #include<iostream>
 #include<cstdio>
 #define LI long int
 #define MAX 100009
 #define MOD 1000000007
 using namespace std;
 LI dp[MAX]={0};
 LI ar[MAX],k,orig;
 void cal(LI n)
 {
       if(n==0)
          return;
       if(dp[n]!=0)
          return;
       LI minn=MAX;
       for(LI i=n-1;i>=0;i--)
       {
          if(ar[n]-ar[i]<=k && ar[n]-ar[i]>=1)
          {
              cal(i);
              minn=(min(dp[i]*ar[n],minn))%MOD;
          }
       }
       dp[n]=minn%MOD;
       return;
 }
 int main()
 {
    LI n,i;
    scanf("%ld %ld",&n,&k);
    orig=n;
    for(i=0;i<n;i++)
       scanf("%ld",&ar[i]);
    dp[0]=ar[0];
    cal(n-1);
    if(dp[n-1]==MAX)
       printf("0");
    else printf("%ld",dp[n-1]);
    return 0;
}

已经2天了,我检查了每一个角落的情况和约束,但它仍然给出错误的答案!解决方案有什么问题?

需要帮助。

分析

有很多问题。以下是我的发现:

  1. 你们毫无理由地将产品限制为低于100009的值。产品可以比这高得多(这确实是问题只要求值模1000000007的原因)
  2. 你限制你在special number差值为K的街道上移动,而问题说明说你可以在index差值小于K的任何城市之间移动
  3. 在动态规划函数中,计算乘积并存储乘积的模。这可能会导致一个问题,因为一个大数字的模可能比一个小数字的模要小。这可能破坏以后的计算。
  4. 您使用的整型long int太短
  5. 你的算法复杂度太高。
在所有这些问题中,最后一个是最严重的。我通过改变整个方法和使用更好的数据结构来修复它。

1的问题

在你的main()函数中:

if(dp[n-1]==MAX)
   printf("0");

在你的cal()函数中:

LI minn=MAX;

你应该将这一行替换为:

LI minn = std::numeric_limits<LI>::max();

不要忘记:

#include <limits>
<<p> 第二问题/strong>
   for(LI i=n-1;i>=0;i--)
   {
      if(ar[n]-ar[i]<=k && ar[n]-ar[i]>=1)
      {
          . . .
      }
   }

你应该替换for循环条件:

  for(LI i=n-1;i>=n-k;i--)

并去掉特殊数的条件。

3

您正在寻找特殊数乘积最小的路径。在当前设置中,在

取乘积的模后比较path的乘积。这是错误的,因为较高的数的模可能会变得非常低(例如,一个路径的乘积是1000000008,它的模是1,你会选择这个路径,即使有一个路径的乘积只有2)。

这意味着你应该比较真实的产品,而不是取它们的模。当这些乘积变得很大时,你应该取它们的对数。这将允许您使用简单的double来比较产品。记住:

log(a*b) = log(a) + log(b)
<<p> 第四问题/strong>

使用unsigned long long

<<p> 第五问题/strong>

我修复了所有这些问题并提交了codechef CHRL4。除了一个测试用例外,我接受了所有测试用例。测试用例未被接受是因为超时。这是因为你的算法的复杂度达到了O(k*n)

您可以使用自下而上的动态规划方法来实现O(n)复杂度,而不是使用自上而下的数据结构,该数据结构将返回k先前街道的最小日志值。您可以查看sliding window minimum algorithm查看如何操作。

引用

  • numeric_limits: max ()
  • 我自己的编解码CHRL4解决方案:自下而上dp +滑动窗口最小值