ackerman函数

Ackerman(阿克曼)函数C语言递归实现       这段时间老师在课提到递归算法的一些应用,我对其中的Ackerman函数比较感兴趣,并尝试探索了一番。       Ackerman函数A(n,m)定义如下(可能跟网上的一些定义有出入):       根据定义,我们知道这是一个非常典型的递归问题,直接上代码解决问题: #include<bits/stdc++.h 阅读详情

递归到非递归的转换

 

一. 为什么要转换
  考虑函数的递归,因为第N次与第N+1次调用所采用的栈不能重用,可能会导致多次调用后,进程分配的栈空间耗尽.
  解决的方法之一就是用自己可控制的栈代替函数调用栈,从而实现递归到非递归的转换.(用户栈当然必须是可以重用的,否则也就没有意义).
  我们将会发现,实际上用户栈相比函数调用栈来说,可以非常小下面就以ackerman函数为例
 
二.ackerman函数
已知Ackerman函数akm(m,n)定义如下:
当m=0时:         akm(m,n) = n + 1;
当m!=0, n=0时:   akm(m,n) = akm(m-1, 1);
当m!=0, n!=0时:  akm(m,n) = akm(m-1, akm(m, n-1));
  
(1) 根据定义,写出它的递归求解算法;
(2) 利用栈,写出它的非递归求解算法。
【解答】
(1) 已知函数本身是递归定义的,所以可以用递归算法来解决:
 unsigned akm ( unsigned m, unsigned n ) {
   if ( m == 0 ) return n+1;      // m == 0
     else if ( n == 0 ) return akm ( m-1, 1 );    // m > 0, n == 0
       else return akm ( m-1, akm ( m, n-1 ) );    // m > 0, n > 0
     }

(2) 为了将递归算法改成非递归算法.
首先改写原来的递归算法,将递归语句从结构中独立出来:
 unsigned akm ( unsigned m, unsigned n ) {
   unsigned v;
    if ( m == 0 ) return n+1;      // m == 0
    if ( n == 0 ) return akm ( m-1, 1 );       // m > 0, n ==0
    v = akm ( m, n-1 ) );        // m > 0, n > 0
   return akm ( m-1, v );
 }
 
然后,就是递归转非递归的标准流程:
a. 从一个简单的实例,分析其递归调用树
b. 分析哪些元素需要放在栈中
c. 跟踪递归调用过程,分析栈的变化
d. 由实例->普遍,演绎出算法,这一过程也称作建模
我们将会发现,建模是最困难的.

下面,我们就以ack(2,1)为例,开始分析递归调用树,采用一个栈记忆每次递归调用时的实参值,每个结点两个域{vm, vn}。对以上实例,递归树以及栈的变化如下:
 

 

 

相应算法如下
#include
#include
using namespace std;
typedef struct node_t {
 unsigned int vm, vn;
}node, *pnode;

unsigned akm ( unsigned int m, unsigned int n ) {
 std::stack st; 
 pnode w, w1;
 unsigned int v;
 unsigned int vt;

 

//根节点进栈
 w = (node *) malloc (sizeof (node));
 w->vm = m; 
  w->vn = n;
  st.push (w);
 
 do {
  //计算akm(m-1, akm(m, n-1))
  while ( st.top( )->vm > 0 ) {            
     vt = w->vn;
     //计算akm(m, n-1), 直到akm(m,0)
     while ( st.top()->vn > 0 )    
     {
       w1 = (node *) malloc (sizeof (node));
       vt --;
       w1->vn = vt;
       w1->vm = w->vm;
       st.push( w1 );
     }

     //把akm(m, 0)转换为akm(m-1, 1),并计算
     w = st.top( ); 
     st.pop( );   
     w->vm--; 
     w->vn = 1; 
     st.push( w );
     vt = w->vn;
  }

  //计算akm( 0, akm( 1, * ) )        
  w = st.top(); 
  st.pop( ); 
  w->vn++; 
  //计算v = akm( 1, * )+1
  v = w->vn;

  //如果栈不为空,改栈顶为( m-1, v )
  if (  !st.empty( ) )     
  {
      w = st.top(); 
      st.pop( );
      w->vm--; 
      w->vn = v; 
      st.push( w );
  }
 } while ( !st.empty( ) );
 return v;
} 

int main()
{
 unsigned int rtn;
 rtn = akm(3,2);
 std::cout << rtn << std::endl;
 return 0;
}

 

三.小结

  主要难点在于最后的建模,怎样从一个或者几个实例,演绎出普适的数学模型,这是我做不到的,只有试图去理解,我想,勤能补拙只不过是一种安慰,真正创造性的工作,的确是聪明人的专利.另外一点感触就是,栈的应用可真是灵活啊!

 

 

 

 

在网上看到了一些人在找这个Ackerman函数 ,

不知道这个函数的实际含义,首先看到了他的递归形式:

注释部分是分析后的结果.

int rackerman(int m,int n)
{
  if(m==0) return n+1; //更新n值,
  else
    if(n==0) return rackerman(m-1,1); //分析后要入栈一次, 同时n更新为 1
    else
      return rackerman(m-1,rackerman(m,n-1));//要先入m-1,然后入m. 同时 n-1
  
}

于是我在纸上模拟了几次栈的进出,发现只用m值在栈中进进出出,而n值是不断更新的,最后返回的值也是n值的变化.

.下面是我的非递归函数:


int
myAckerman(int m , int n )
{
    list<int > listM;
    listM.push_back(m);

    while(! listM.empty() )
    {
        m=listM.back();
        listM.pop_back();

        if ( ! m ) 
        {
            n=n+1;
        }
        else if ( ! n ) 
        {
            m=m-1;
            n=1;
            listM.push_back(m);
        }
        else
        {    
            n=n-1;
            listM.push_back(m-1);
            listM.push_back(m);
        }
    }
    return n;
}

 

递归方法最简单,不需要说明。

  #include "stdafx.h"
#include <iostream>
#include "time.h"

using std::cout;
using std::endl;

 

unsigned int akm(unsigned int m , unsigned int n)
...{
    if(m==0) return n+1;
    else if( n==0 ) return akm(m-1,1);
    else return  akm(m-1, akm(m,n-1));

}


int main(int argc, char* argv[])
...{
   time_t x, y;
    x = time(0);
    cout<<"akm(1, 0) =  "<<akm(1,0)<<endl;
    y = time(0);
    cout <<"using time is " << difftime(y, x) <<endl;

    return 0;
}用for循环:
注意,申请的内存空间要足够大,反正我的计算机已经提出警告了,只能申请256M的内存。为什么要申请这么大的空间呢?由于ackerman是嵌套函数,他的值随时用来作为另外一个 函数的下标。因此,要申请足够的空间。不要以为只需要求ackerman(m, n)就for循环到m, n为止,这是错误的。
    #include "stdafx.h"
#include <iostream>

using std::cout;
using std::endl;

const int maxN = 8500;
static int akm[maxN][maxN] =...{0};


int Ackerman(int m, int n)
...{
  for(int j = 0; j <maxN; j++)
     akm[0][j] = j+1;
  for(int i = 1; i <maxN; i++)
  ...{
    akm[i][0] = akm[i-1][1];
    for(j = 1; j <= maxN; j++)
    ...{
       akm[i][j] = akm[i-1][akm[i][j-1]];
    }
  }
   return akm[m][n];
}
int main(int argc, char* argv[])
...{   
    
            cout<<"akm["<<3<<"]"<<"["<<9<<"]"<<" = "<<Ackerman(3, 9)<<endl;
             cout<<"akm["<<3<<"]"<<"["<<10<<"]"<<" = "<<Ackerman(3, 10)<<endl;

    
    
    return 0;
}
/
。
//以下方法被称为“备忘”。
可以,参看《算法导论》这本书的线性规划的后面部分。
同时必须指出:仍然申请的空间要足够的大,原因同上。否则要出错。
这个最多能算到ackerman(3,10) .内存大的应该还可以计算更大的。此种方法较为简单。

#include "stdafx.h"
#include <iostream>
#include "time.h"
const int maxN = 8500;
using std::cout;
using std::endl;

static int Ack[maxN][maxN];
void inint(void )
...{
    for(int i = 0; i <maxN; i++)
        for(int j = 0; j <maxN; j++)
            Ack[i][j] = 0;
}

int Ackerman(int m, int n)
...{   
    int t = 0;
    if(Ack[m][n] != 0)
        return Ack[m][n];
    if( m ==0 )
         return n+1;
    if ( n==0 )
         t = Ackerman(m-1, 1);
    if(m >=1 && n >= 1)...{
         Ack[m][n-1] = Ackerman(m, n-1);
         t = Ackerman(m-1, Ack[m][n-1]);
    }
    
    
    return  (Ack[m][n] = t); 
}
int main(int argc, char* argv[])
...{  
    time_t start, end;
    inint();
    
    start = time(0);
    
    for(int i = 0 ; i <= 3; i++)
        for(int j = 0; j <= 10; j++)
            cout<<"Ack["<<i<<"]"<<"["<<j<<"]"<<" = "<<Ackerman(i, j)<<endl;
    end = time(0);
    cout<<"using time is "<<difftime(end, start)<<endl; 
   

    
    return 0;
}

 

Ackerman 函数的解法
1.定义

    ack(m,n) =  n+1                     m = 0
    ack(m,n) = ack(m-1,1)            m!=0  n = 0
    ack(m,n) = ack(m-1,ack(m,n-1))        m!=0  n!=0

2.示例
     ack(3,0) = (2,1) 
                 = (1,(2,0))
                 = (1,( 1,1))
                 = (1,(0,(1,0)))
                 = (1,(0,(0,1))
                 = (1,(0,2))
                 = (1,3)
                 = (0,(1,2))
                 =(0,(0,( 1,1))
                 ...
                 =(0,(0,3))
                 ...
                 = 5  

3.复杂性分析
 待解决,m>5后复杂度极高。


4.最简单的递归解法
//按照函数的递归定义即可

    int ack(int m, int n)
    {
         if (m == 0)
          return n+1;

         if (n == 0)
          return ack(m-1, 1);

         return ack(m-1, ack(m,n-1));

    }

5.去掉递归,用栈保存信息
/*
 *  n = 0 的时候往下递归其实只有一个递归分支,无需保留信息,可以用循环取代的
 *  而 对于 m!=0 && n!=0 的情况 注意到是一个迭代递归
 *  这其中 注意 我们用到 ack(m,n-1)的返回值作为 ack(m-1,x)的值
 *  事实上只需要m入栈,使得我们在进入到 ack(m,n-1)后最后能够返回出来计算 ack(m-1,x) x = ack(m,n-1)
 */

下面给出 带 goto 和不带 goto 语句的两种解法
int ack_goto(int m, int n)
{
int result;
stack<int> stk;

start:
if (m == 0)
{
result = n+1;
if (stk.empty())
{
goto end;
} 
else
{
goto qiantao;
}
}
else if (n == 0)
{
m = m-1;
n = 1;
goto start;
}
else
{
m = m;
n = n-1;
stk.push(m);   //为了保留当期信息,只需保留m等待 右面嵌套返回结果继续
goto start;
qiantao:
m = stk.top();
stk.pop();
m = m-1;
n = result;
goto start;
}


end:
return result;
}



//机械式的对递归程序的用栈标准的非递归翻译
int ack_norec(int m, int n)
{
stack<int> stk;

stk.push(m);

while (!stk.empty())
{
m = stk.top();
stk.pop();
if (m == 0)
{
n = n+1;

}
else if (n == 0)
{
m = m-1;
n = 1;
stk.push(m);
}
else
{
m = m;
n = n-1;
stk.push(m-1);
stk.push(m);
}
}

return n;

}

5.对于以上基于定义用递归或是用栈消除递归的做法,有没有可能优化呢?
   对于示例 ack(3,0) 可以注意到 ack(1,1)出现了两次,对于上面的解法,ack(1,1)也就被计算了两次。
   事实上我们可以记录已经做好的中间结果,避免重复的递归,也就是所谓的剪枝。

    5.1递归加剪枝
        const int mMax = 5;
        const int nMax = 1000000;
        int ackV[mMax][nMax];
        bool got[mMax][nMax];       //注意全部初始为false

        int ack2(int m, int n)
        {
   if (m > mMax || n > nMax)
   {
cout << "error input too large" << endl;
exit(1);
   }
   if (got[m][n] == true)
return ackV[m][n];

   if (m == 0)
return n+1;
   if (n == 0 )
return ack2(m-1,1);

   ackV[m][n] = ack2(m-1,ack2(m,n-1));
   got[m][n] = true;
   return ackV[m][n];
        }
     
    5.2非递归算法的优化
         int ack_norec2(int m, int n)
        {
            if (m > mMax || n > nMax)
   {
cout << "error input too large" << endl;
exit(1);
   }

   stack<int> stk;
   stack<int> stk2;
   int result;
   bool flag = 0;

   stk.push(m);

   while (!stk.empty())
   {
                     if (n > nMax)
           {
       cout << "error input too large" << endl;
       exit(1);
           }
   m = stk.top();
   stk.pop();
  
   if (flag == 1)
   {
   if (got[m+1][stk2.top()] == false)
   {
     ackV[m+1][stk2.top()] = n;
   got[m+1][stk2.top()] = true;
   }
   stk2.pop();
   flag = 0;
   }
   if (got[m][n] == true)
   {
   n = ackV[m][n];   //退出口
           flag = 1;          //尽管不需要记录这个结果了但因为n已经被Push了要出栈
   continue;
   }

   if (m == 0)
   {
   n = n+1;          //退出口
   flag = 1;

   }
   else if (n == 0)
   {
   m = m-1;
   n = 1;
   stk.push(m);
   }
   else
   {
   m = m;
   n = n-1;
   stk.push(m-1);
   stk2.push(n);
   stk.push(m);
   }
       }

   return n;
        }

    
6.动态规划,记录前面的结果,空间换时间


   这么经典的递归函数不用递归来做,太可惜了。
不过在C语言中,一个函数是不能作为函数的形参进行传输的,只有特定的变量才能进行函数形参的传递.
这个函数用递归写成这样是错的吧??
#include<stdio.h>
int ack(int m,int n)
{
if(m==0) return (n+1);
else if(n==0) return ack(m-1,1);
else return ack(m-1,ack(m,n-1));  
}
void main()
{
int m,n;
printf("input m n:/n");
scanf("%d %d",&m,&n);
    printf("ack(%d,%d)=%d/n",m,n,ack(m,n));
getch();
}
我写了个基于二维数组的消除递归的算法如下(也可以用栈消除递归)理论上这样可行,存储空间的范围定30*30以内:
#include<stdio.h>
#define MAX 30
/*范围定为30,可改大点*/
int Ackerman(int m,int n)
{
int i,j;
int t;
int a[MAX][MAX];/*存放结果*/
for(i=0;i<MAX;i++)
    for(j=0;j<20;j++)
        a[i][j]=0;  /*数组初始化*/
for(j=0;j<MAX;j++)
    a[0][j]=j+1;      /* A(m,n)=n+1,   若 m=0*/
while(a[m][n] == 0)  /*结果出来后结束循环*/
{
    for(i=0;i<MAX;i++)
        if(a[i-1][1]!= 0)
            a[i][0]=a[i-1][1];   /*  A(m,n)=[A(m-1,1), 若n=0 */
    for(i=1;i<MAX;i++)
       for(j=1;j<20;j++)
            {
            if((a[i][j-1] != 0)&&(a[i][j]==0) )
                {
                    t=a[i][j-1];
                    if((a[i-1][t] != 0))
                        a[i][j]=a[i-1][t];  /*  A(m-1,A(m,n-1)), 其他 */
                }
            }
}
return a[m][n];
}
int main()
{
int m,n;
printf("input m n:/n");
scanf("%d %d",&m,&n);
printf("ack(m,n)=%d/n",Ackerman(m,n)); 
return 0;
}

理论上一定会有结果,时间复杂度在MAX的四次方内.
但是实际上当m n稍微大点就会需要大于30的数组才能计算,尤其是m不能大(3以内).
否则很容易陷入死循环,
因为定义的数组不够大,硬件和时间限制,呵呵
当然不想死循环可以限制while循环次数为n*m,超过这个次数没结果的话基本就算不出来的了。

Ackerman函数 的 递归思路 Hello,everybody.我是Aqin! 很高兴能和大家聊聊编程(C++)! 这次的题目如下: 题目描述 计算ackerman函数值: 输入格式 从文件ackerman.in读入数据,第一行为两个数,即M和N,其中0<=M<=3,0<=N<=11。 输出格式 向文件ackerman.out输出ack(m,n)的值。 输入样例 0 1 输出样例 2 初看此题,大家会想到什么? 不用说,当然是 递归 啦! 那么究竟怎么做呢? 代码如下:(详解见代码中) //开O2才能过,建议 阅读详情

相关推荐

【记忆化】ackerman函数

1、ackerman函数 ( ackerman.pas/cpp/c ) 问题描述: 计算ackerman函数值:   输入格式: 从文件ackerman.in读入数据,第一行为两个数,即M和N,其中0   输出格式: 向文件ackerman.out输出ack(m,n)的值。   样例1: ackerman.in ackerman.out

Jiangzh_MZOI 1690

Ackerman函数

Ackerman函数在许多讲解递归的书中都提到,但似乎又对解题没有太大的意义,暂时不知道了。不过这个东西,是一个数学知识点,暂时收藏于此吧。 查了一下维基百科和百度百科,表面上两个定义不一样,仔细推敲其实是一样的。(维基百科里面A(m,n)和百度百科里面A(n,m)当中的参数n、m代表含义是一样的,只是它们两个递归函数的参数的顺序写的不一样而已。) 下面看看Ackerman函数: Fibonacci数列可以写出通项公式,就是用非递归的方式去下定义。但并非一切的递归函数都能用非递归方式去定义。下面讲一个

qq_44805265的博客 4900

Ackermann 函数:一个简单的 Matlab 函数来计算 Ackermann 函数。-matlab开发

由数学家 Willhelm Ackermann 开发的 Ackerman 函数以其极快的增长速度令人印象深刻,并具有更多迷人的功能。 有了这个简单的代码,Ackermann 函数就可以在 Matlab 中轻松使用。

java中的ackerman_Ackerman函数

Ackerman函数在许多讲解递归的书中都提到,但似乎又对解题没有太大的意义,暂时不知道了。不过这个东西,是一个数学知识点,暂时收藏于此吧。查了一下维基百科和百度百科,表面上两个定义不一样,仔细推敲其实是一样的。(维基百科里面A(m,n)和百度百科里面A(n,m)当中的参数n、m代表含义是一样的,只是它们两个递归函数的参数的顺序写的不一样而已。)先看Fibonacci数列Fibonacci数列是一...

weixin_39572409的博客 354

ackerman函数_ackerman函数_

算法设计与分析。ackerman函数的实现。语言:c++

从BUCK-BOOST到反激:一个‘拆电感’的视角,轻松理解多路输出交叉调整

本文从BUCK-BOOST电路到反激变换器的演变入手,通过‘拆解电感’的独特视角解析多路输出交叉调整机制。深入探讨了反激电路的能量暂存方式、传递路径变化及电压关系,并结合具体参数对比揭示其特性。针对多路输出中的电压平衡问题,提供了绕组排布优化、元器件选型等实战技巧,帮助工程师有效提升电源系统的稳定性与效率。

weixin_33738578的博客 436

递归之Ackerman函数

并非一切的递归函数都能用非递归方式定义。 Ackerman函数是一个双递归函数,当一个函数以及它的一个变量是由函数自身定义时,称为双递归函数。 Ackerman是一个双递归函数A(N,M) 函数定义如下:A(1,0)=2; A(0,m)=1; m>=0 A(n,0)=n+2; n>=2 A(n,m)=A(A(n-1,m),m-1); n,m>=1 推理可得:A(n,0)定

QS_Sun_24的博客 2678

RTOS任务调度原理:高优先级任务为何在低优先级任务执行时无法响应

实时操作系统(RTOS)的核心在于其确定性的任务调度机制,它通过优先级抢占确保关键任务及时执行。其基本原理是调度器仅在特定调度点(如任务主动阻塞、中断退出时)运行,比较就绪态任务的优先级并切换上下文。这一机制的技术价值在于为嵌入式系统提供可预测的响应时间,广泛应用于工业控制、汽车电子和物联网设备等对实时性要求高的场景。当低优先级任务执行**长时间非阻塞运算**且无中断发生时,调度器无法被触发,导致高优先级任务虽处于就绪态却无法获得CPU,造成系统响应延迟。理解**任务状态机**与调度点,是优化实时性、避免此

weixin_33508411的博客 287

Ackerman函数的非递归实现.

在网上看到了一些人在找这个Ackerman函数 ,不知道这个函数的实际含义,首先看到了他的递归形式:注释部分是分析后的结果.int rackerman(int m,int n){  if(m==0) return n+1; //更新n值,  else    if(n==0) return rackerman(m-1,1); //分析后要入栈一次, 同时n更新为 1    else   

swankie的专栏 1万+

Zemax操作40--序列模式中LD光源模拟

LD模拟

lzy750750的博客 9118

YOLOv10改进策略【模型轻量化】| 替换骨干网络为MoblieNetV2,含模型详解和完整配置步骤

本文记录的是。采用深度可分离卷积将标准卷积分解为深度卷积和1×1卷积。同时,引入来,避免非线性层导致的性能下降问题。本文将应用到YOLOv10中,借助其高效的结构和特性,在保持一定精度的前提下,显著降低YOLOv10的计算复杂度和内存占用。

Limiiiing的博客 532

Ackerman函数 非递归 java_ackerman(ackerman是谁)

Ackerman指的是由于转向系统的几何形状,使车辆转向时内侧轮比外侧轮转动更多的角度。 什么是Ackerman?由于车辆转弯时内外轮的行驶半径不同,Ackerman可以帮.【人名】 [英格兰人姓氏] 阿克曼 Acker的变体;封建制度下的佃农 【地名】 [美国] 阿克曼;mikasa·ackerman三笠·阿克曼很高兴为你解答!如有不懂,请追问。 谢谢!Ackerman释义[人名] [英格兰人姓...

weixin_32708653的博客 481

(王道408考研操作系统)第三章内存管理-第一节1:内存基础知识、程序编译运行原理

注意:本节内容和《计算机组成原理》“存储器”那一部分内容相关性很强,组成原理是从硬件角度,操作系统是从软件角度。因此如果没有学习过这部分的同学,强烈建议先看这一部分 王道计算机组成原理笔记 本文主要会涉及以下必要的内存知识 文章目录一:内存及其作用 一:内存及其作用 内存:内存又称之为主存。是一种硬件设备,作为CPU和硬盘的缓冲区,用于解决其速度不匹配的问题,提高整机性能。程序执行前需要放入内存才能运行 ...

快乐江湖的博客 2790

递归 Ackerman函数

当一个函数以及它的一个变量由函数自身定义时,称这个函数为双递归函数———Ackerman函数。 Ackerman函数A(n,m)有两个独立的变量m≥0和n≥0,其定义如下: A(1,0)=2 A(0,m)=1                                              m≥0 A(n,0)=n+2                                

Candy_GL的博客 3210

Google Earth Engine:LandTrendr (Landsat Collection 2)全更新使用(代码调用+UI交互)

本文介绍了使用Landsat Collection 2进行连续变化监测的分析方法,包含代码实现和可视化界面两部分。代码部分通过Google Earth Engine平台运行LandTrendr算法,设置参数包括时间范围、光谱指数、变化检测阈值等,最终生成变化幅度和检测年份的可视化图层,并将结果导出至Google Drive。可视化界面部分展示了基于LandTrendr的土地覆盖变化结果,结合Landsat影像进行分析。整个方法实现了从数据处理到结果展示的完整流程,适用于森林覆盖等环境变化监测。

此星光明博客 210

点云焊缝提取

本文介绍了一个基于PCL库的点云处理流程,包含三个核心模块:MLS平滑处理通过多项式拟合修正点云位置;差异提取通过双向匹配定位源/目标点云的非重叠区域;统计过滤剔除离群噪声点。该流程采用"平滑-筛选-净化"的通用思路,将复杂算法封装为可配置接口,实现了工业级点云预处理。文章重点分析了各模块的原理、PCL接口调用及参数设计逻辑,同时指出参数调优、算法扩展等深入探索方向,展现了PCL在点云处理中的模块化优势与实用价值。

weixin_45196569的博客 250

如何使用栈非递归地求解Ackerman函数

Ackerman 函数如下: 如果用递归算法求 A(m, n) 非常简单: int Ackerman(m, n) { if(m==0) return n+1; else if(m&gt;0 &amp;&amp; n==0) return Ackerman(m-1, 1); else if(m&gt;0 &amp;&amp; n&gt...

一个女程序员的博客 6206

VTK API 详解(103):vtkGPUVolumeRayCastMapper - GPU加速体绘制

是 VTK 中基于 GPU 的高效体绘制映射器,利用现代显卡的计算能力,通过射线投射算法实现快速且高质量的三维体积渲染。相比 CPU 版本的,GPU 映射器性能大幅提升,支持更复杂的光照和渲染效果,是体绘制的主流选择。是 VTK 中性能优异的GPU体绘制映射器;适合大数据集和实时交互应用;配合灵活设置颜色、透明度和光照;建议在支持OpenGL的环境中使用。

yumeiguo的博客 292

Ackerman函数 非递归 java_Ackerman函数的非递归实现.

在网上看到了一些人在找这个Ackerman函数,不知道这个函数的实际含义,首先看到了他的递归形式:注释部分是分析后的结果.int rackerman(int m,int n){if(m==0) return n+1; //更新n值,elseif(n==0) return rackerman(m-1,1); //分析后要入栈一次,同时n更新为 1elsereturn rackerman(m-1,...

weixin_32263265的博客 506

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Ackerman函数(递归与非递归算法实现)

Ackerman函数 阿克曼函数是非原始递归函数的例子;它需要两个自然数作为输入值,输出一个自然数。它的输出值增长速度非常高。 计算Ackerman(m,n)函数递归算法与非递归算法(利用顺序栈) import java.util.Scanner; public class SequenceStack<T> { public static void main(String[] args) { Scanner scanner =new Scanner(S...

flow 2989

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Ackerman函数(C语言)

Ackerman函数递归实现(C语言) 此函数在此不做详细介绍。下面直接上代码。 输入样例: 4 3 输出样例: 65536 源代码 #include<stdio.h> int Ackerman(int n, int m) { if(n<0 || m<0) return 0; else if(n==1 && m ==0) return 2; else if(n==0 && m>=0)

qq_44971979的博客 3973

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: 关于co-NP的理解
下一篇: 库克列文定理的证明
Savitch
博客等级 码龄16年 84粉丝 130原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值