给出一个整数数组,m =移动数。从索引0开始。每次移动都可以向前或向后执行arr [i]步骤。如果m变为0。并且您位于最后一个位置,则打印true,否则打印false。
例如: arr包含元素2,3,1。 m = 1; 答:是的; 说明:i = 0处的值为2,因此,对于m = 1,向前走2步,您将到达终点位置。是的,真的。
我尝试了以下代码,但未打印正确答案: num_ele是数组中元素的总数。
bool fun(int arr[],int m,int i,int num_ele)
{
if(m==0)
{
if(i==(num_ele)
return true;
else
return false;
}
fun(arr,m-1,i+arr[i],num_ele);
fun(arr,m-1,i-arr[i],num_ele);
}
答案 0 :(得分:0)
此问题等同于确定二进制字母上的确定性有限自动机是否接受长度为m的字符串的问题。要构造自动机,请添加与数组元素一样多的状态,并添加两个转换来表示向左或向右移动相应的位置数。使对应于最后一个数组元素的状态为接受状态,并使对应于第一个数组元素的状态为初始状态。
接下来,构造一个确定性有限自动机,该自动机接受长度为n的所有二进制字符串。此DFA将具有n + 1个状态,一个初始状态和一个接受状态。
接下来,使用笛卡尔乘积机器构造为这些DFA语言的交集构建DFA。对于上述两个DFA中的每对状态,该DFA都将有一个状态,将从对应于一对初始状态的状态开始,并终止于与接受状态对对应的状态。
最后,确定此DFA的语言是否为空语言。广度优先或深度优先搜索,或者最小化然后与空语言的DFA比较就足够了。
从两个具有n和n + 1状态的DFA开始;构造具有n(n + 1)个状态的DFA;然后查看它是否接受字符串。复杂度应为O(n ^ 2)。
答案 1 :(得分:0)
可以使用C#语法按如下方式实现。
bool fun(int[] arr, int m, int i)
{
if (0 == m) // base case - if no moves are left, decide
{ // whether the end of the array is reached
return i == arr.Length-1 ;
}
else
{
int LeftPos = i+arr[i];
int RightPos = i-arr[i];
bool ResultLeft = 0 <= LeftPos
&& LeftPos =< arr.Length-1
&& fun(arr, m-1, LeftPos);
bool ResultRight = 0 <= RightPos
&& RightPos =< arr.Length-1
&& fun(arr, m-1, RightPos);
return ResultLeft || ResultRight;
}
}
该实现进行一些边界检查,以检查结果位置是否仍在数组内部。注意,可以捷径求值;如果其中一个递归调用返回true
,则不必评估另一个调用。话虽如此,索引检查可以在调用中首先完成;因此,该实现将受益于||
运算符的简短行为,如下所示。
bool fun(int[] arr, int m, int i)
{
if (i < 0 || i > arr.Length-1) // index checking
{
return false;
}
else
{
if (0 == m) // base case - if no moves are left, decide
{ // whether the end of the array is reached
return i == arr.Length-1 ;
}
else // compund case - decide whether moving left
{ // or right yields the end position
return fun(arr, m-1, i+arr[i]) || fun(arr, m-1, i-arr[i]);
}
}
}