在codechef上解决此问题:
在拜访了一个儿时的朋友之后,厨师想回到他的家。朋友住在第一条街,而厨师本人则住在第N条(也是最后一条)街。他们的城市有点特殊:当且仅当1 <= Y-X <= K,并且其中K是提供给您的整数值时,您才可以从X街移至Y街。厨师要以这样一种方式回家:所有访问过的街道的特殊号码的乘积最小(包括第一条和第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来解决它。我的方法:
代码:
#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;
}
已经两天了,我检查了每个极端的情况和限制条件,但仍然给出错误的答案!解决方案出了什么问题?
需要帮忙。
分析
有很多问题。这是我发现的:
100009
无缘无故地将产品的价值限制在较低的水平。乘积可能会更高(这确实是问题仅要求取模值的原因1000000007
)special number
是K
,而问题的声明说,你可以任何其城市之间移动index
的差异不如K
long int
太短。从所有这些问题来看,最后一个是最严重的。我通过更改整个方法并使用更好的数据结构来解决此问题。
第一个问题
在您的main()
职能中:
if(dp[n-1]==MAX)
printf("0");
在您的cal()
职能中:
LI minn=MAX;
您应将此行替换为:
LI minn = std::numeric_limits<LI>::max();
不要忘记:
#include <limits>
第二个问题
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--)
并完全删除特殊数字上的条件。
第三题
您正在寻找特殊数字乘积最低的路径。在当前设置中,您在对乘积取模后比较路径的乘积。这是错误的,因为更高的模数可能会变得很低(例如,其乘积为1000000008
模的路径将具有模的模数,1
并且即使有一个乘积为的路径,您也将选择此路径2
)。
这意味着您应该比较真实的产品,而不用取它们的模。这些产品的价格可能会很高,因此您应该采用对数。这将使您可以将产品与简单产品进行比较double
。请记住:
log(a*b) = log(a) + log(b)
第四题
使用unsigned long long
。
第五题
我解决了所有这些问题,并提交了Codechef CHRL4。除了一个测试用例,我都接受了。无法接受的测试用例是因为超时。这是由于您的算法的复杂度为O(k*n)
。
您可以O(n)
使用自下而上的动态编程方法(而不是自上而下)并使用将返回k
先前街道的最小日志值的数据结构来实现复杂性。您可以查找sliding window minimum algorithm
以查找操作方法。
参考
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句