C++ 动态规划算法

C++ 动态规划算法,c++,algorithm,C++,Algorithm,嗨,我有一个关于现有算法问题的问题 存在的问题说明: 虽然这个问题有C++的标记,但是考虑这个伪代码来表达算法(它恰好是用Ruby编写的)< < 结果是从键k开始的所有n长度序列的数量,其中不超过3个偶数。例如,最后一个条目是k=9,n=8:0。这意味着从键9开始的长度为8的所有序列都包含3个以上的偶数数字 编辑:这里被翻译成C++。它产生与上述相同的输出 #include<iostream> #include<map> using namespace std; con

嗨,我有一个关于现有算法问题的问题

存在的问题说明:


虽然这个问题有C++的标记,但是考虑这个伪代码来表达算法(它恰好是用Ruby编写的)< < 结果是从键
k
开始的所有
n
长度序列的数量,其中不超过3个偶数。例如,最后一个条目是
k=9,n=8:0
。这意味着从键9开始的长度为8的所有序列都包含3个以上的偶数数字

<>编辑:这里被翻译成C++。它产生与上述相同的输出

#include<iostream>
#include<map>
using namespace std;

const int MAX_EVENS = 3; // Assume < 8

// Where the knight can jump to
const int jumpto[][3] = { {4,6}, // 0
  {6,8}, {7,9}, {4,8},   // 1 2 3
  {0,3,9}, {}, {0,1,7},  // 4 5 6
  {2,6}, {1,3}, {2,4} }; // 7 8 9
const int jumpto_size[] = { 2, // 0
  2, 2, 2,   // 1 2 3
  3, 0, 3,   // 4 5 6
  2, 2, 2 }; // 7 8 9

typedef map<unsigned,int> cachetype;
cachetype cache;

int nseq( int k, int n, int e=0 )
{
  e += k&1^1; // increment e if k is even.
  if( MAX_EVENS < e ) return 0;
  if( n <= 1 ) return 1;
  unsigned key = (n << 4 | k) << 3 | e; // n is left with 32-7=25 bits
  cachetype::const_iterator it = cache.find(key);
  if( it != cache.end() ) return it->second;
  int sum = 0;
  for( int i=0 ; i<jumpto_size[k] ; ++i ) sum += nseq( jumpto[k][i], n-1, e );
  return cache[key] = sum;
}

int main()
{
  for( int k=0 ; k<=9 ; ++k )
    for( int n=2 ; n<=8 ; ++n )
    {
      int count = nseq(k,n);
      cout << "k="<<k<<",n="<<n<<": "<<count<<endl;
      if( count == 0 ) break;
    }
  return 0;
}
#包括
#包括
使用名称空间std;
常量int MAX_EVENS=3;//假设<8
//骑士可以跳到哪里
const int jumpto[][3]={{4,6},//0
{6,8}, {7,9}, {4,8},   // 1 2 3
{0,3,9}, {}, {0,1,7},  // 4 5 6
{2,6}, {1,3}, {2,4} }; // 7 8 9
const int jumpto_size[]={2,//0
2, 2, 2,   // 1 2 3
3, 0, 3,   // 4 5 6
2, 2, 2 }; // 7 8 9
typedef映射缓存类型;
缓存类型缓存;
int nseq(int k,int n,int e=0)
{
e+=k&1^1;//如果k是偶数,则增加e。
如果(MAX_EVENS如果(n)如果解决原始问题的递归函数具有函数签名
int count(int n)
,则新问题的解决方案具有函数签名
pair count2(int n,int e=0)
通过
e
跟踪序列中偶数位数的位置,并在返回值中同时返回
n
e
。如果在任何点
e>3
,则返回
n=0
@Matt:为什么返回
e
?并非所有序列都是相同的。对序列发生了什么“结束位置”论点?@BenVoigt是的,你是对的。请看我的答案。你的问题是什么?你能完整地回答这个问题吗?这样我们就不必按照链接来找出你在问什么了?
$m[k]。注入(0){{sum,j | sum+nseq(j,n-1,e)}
-那(除其他外)在我的书中,它远远没有使用足够通用的语法来分类为正确的伪代码。用其他语言编写的代码!=伪代码。@Dukeling对此没有异议。这一行特别总结了
nseq(j,n-1,e)
,因为j随
$m[k]
而变化。例如
k=1
这等于
nseq(6,n-1,e)+nseq(8,n-1,e)。@ bj飞飞,因为它不完整,所以我很难彻底检查你的代码。具体来说,它不包含<代码> GAMEDATA < /Cord>类,所以我必须做太多的猜测,以便明确地批评你的代码。相反,我将Ruby代码改写成C++。最大偶数位数,如上面的输出所验证的,最大序列长度为64。因此,对于
k
n
的任何值,
nseq(k,n)
的调用次数不超过最大值的54倍(这很容易通过每次调用nseq()时增加一个全局变量来确认)所以对于
n>=7
,时间复杂度是O(1)。如果最大偶数本身被认为是一个参数,那么时间和空间复杂度将取决于这两个参数和
n
。也许其他人,包括你自己,可以精确地计算。打字-我的意思是“…最大序列长度是7”(其中有64个从1开始),通过上述输出进行验证。”
# Where the knight can jump to
$m = {
  0 => [4,6], 1 => [6,8], 2 => [7,9], 3 => [4,8], 4 => [0,3,9],
  5 => [], 6 => [0,1,7], 7 => [2,6], 8 => [1,3], 9 => [2,4]
}

$cache = Hash.new
# return count
def nseq( k, n, e=0 )
  e += 1 if k.even?
  return 0 if 3 < e
  return 1 if n == 1
  key = "#{k}:#{n}:#{e}" # for the memoization
  return $cache[key] if $cache.has_key? key
  # Sum nseq(j,n-1,e) for j in $m[k]
  return $cache[key] = $m[k].inject(0) { |sum,j| sum + nseq( j, n-1, e ) }
end

0.upto(9) do |k|
  2.upto(8) do |n|
    count = nseq(k,n)
    puts "k=#{k},n=#{n}: #{count}"
    break if count.zero?
  end
end
k=0,n=2: 2
k=0,n=3: 6
k=0,n=4: 8
k=0,n=5: 16
k=0,n=6: 0
k=1,n=2: 2
k=1,n=3: 5
k=1,n=4: 10
k=1,n=5: 24
k=1,n=6: 32
k=1,n=7: 64
k=1,n=8: 0
k=2,n=2: 2
k=2,n=3: 4
k=2,n=4: 10
k=2,n=5: 16
k=2,n=6: 32
k=2,n=7: 0
k=3,n=2: 2
k=3,n=3: 5
k=3,n=4: 10
k=3,n=5: 24
k=3,n=6: 32
k=3,n=7: 64
k=3,n=8: 0
k=4,n=2: 3
k=4,n=3: 6
k=4,n=4: 14
k=4,n=5: 16
k=4,n=6: 32
k=4,n=7: 0
k=5,n=2: 0
k=6,n=2: 3
k=6,n=3: 6
k=6,n=4: 14
k=6,n=5: 16
k=6,n=6: 32
k=6,n=7: 0
k=7,n=2: 2
k=7,n=3: 5
k=7,n=4: 10
k=7,n=5: 24
k=7,n=6: 32
k=7,n=7: 64
k=7,n=8: 0
k=8,n=2: 2
k=8,n=3: 4
k=8,n=4: 10
k=8,n=5: 16
k=8,n=6: 32
k=8,n=7: 0
k=9,n=2: 2
k=9,n=3: 5
k=9,n=4: 10
k=9,n=5: 24
k=9,n=6: 32
k=9,n=7: 64
k=9,n=8: 0
#include<iostream>
#include<map>
using namespace std;

const int MAX_EVENS = 3; // Assume < 8

// Where the knight can jump to
const int jumpto[][3] = { {4,6}, // 0
  {6,8}, {7,9}, {4,8},   // 1 2 3
  {0,3,9}, {}, {0,1,7},  // 4 5 6
  {2,6}, {1,3}, {2,4} }; // 7 8 9
const int jumpto_size[] = { 2, // 0
  2, 2, 2,   // 1 2 3
  3, 0, 3,   // 4 5 6
  2, 2, 2 }; // 7 8 9

typedef map<unsigned,int> cachetype;
cachetype cache;

int nseq( int k, int n, int e=0 )
{
  e += k&1^1; // increment e if k is even.
  if( MAX_EVENS < e ) return 0;
  if( n <= 1 ) return 1;
  unsigned key = (n << 4 | k) << 3 | e; // n is left with 32-7=25 bits
  cachetype::const_iterator it = cache.find(key);
  if( it != cache.end() ) return it->second;
  int sum = 0;
  for( int i=0 ; i<jumpto_size[k] ; ++i ) sum += nseq( jumpto[k][i], n-1, e );
  return cache[key] = sum;
}

int main()
{
  for( int k=0 ; k<=9 ; ++k )
    for( int n=2 ; n<=8 ; ++n )
    {
      int count = nseq(k,n);
      cout << "k="<<k<<",n="<<n<<": "<<count<<endl;
      if( count == 0 ) break;
    }
  return 0;
}