赞
踩
// 阶乘函数
int factorial(int x)
{
if(x == 0)
return 1;
return x*factorial(x-1);
}
// Fibonacci数列
int fibonacci(int x)
{
if(x<=1)
return 1;
return fibonacci(x-1) + fibonacci(x-2);
}
// 全排列问题 int permutation(int *arr, int pos, int n) { // 边界条件 if(pos == n) { print_arr(arr, n); return 0; } for(int i=pos, i<n; i++) { swap(arr, i, pos); permutation(arr, pos+1, n); swap(arr, i, pos); } return 0; }
将整数n表示成一系列正整数之和
在本题中,如果设p(n)为正整数n的划分数,则难以找到递归关系,因此考虑增加一个自变量:
将n最大加数不大于m的划分数个数记为q(n,m)
可以建立q(n,m)的如下递归关系
将A上n-1个圆盘移到C上,再将最后一个圆盘移到B上,最后将C上n-1个圆盘移到B上。
void hanoi(int n, int a, int b, int c)
{
hanoi(n-1, a, c, b);
move(a, b);
hanoi(n-1, c, b, a);
}
分治法所能解决的问题一般具有以下几个特征:
divide-and-conquer(p)
{
if(|p| <= n0) adhoc(p); // 解决小规模问题
divide p into smaller subinstances p1,p2,...pk; // 分解问题
for(i=0; i<=k; i++) // 参考全排列子问题
yi = divide-and-conquer(pi); // 递归的解各子问题
return merge(y1,...,yk); // 将各子问题的解合并为原问题的解
}
在用分治法设计算法时,最好使子问题的规模大致相同。即将一个问题分成大小相等的k个子问题的处理方法是行之有效的。这种使子问题规模大致相等的做法是出自一种平衡子问题的思想,它几乎总是比子问题规模不等的做法要好。
一个分治法将规模为n的问题分成k个规模为n/m的子问题去解。设分解阈值n0=1 ,且adhoc解规模为1的问题耗费1个单位时间。再设将原问题分解为k个子问题以及用merge将k个子问题的解合并为原问题的解需要f(n)个单位时间。则T(n)表示该分治法解规模为|p| = n的问题所需的计算时间,则有:
template<class Type> int BinarySearch(Type a[], const Type& x, int n) { int left = 0, right = n-1; //找到x返回其在数组中的位置,否则返回-1 while(left <= right) { int middle = (left + right) / 2; if(x == a[middle]) return middle; if(x > a[middle]) left = middle + 1; else right = middle - 1; } return -1; // 未找到x }
// tr, tc:棋盘左上角行坐标,列坐标 // dr, dc:特殊方格的行坐标,列坐标 // size: 棋盘的行/列数 void ChessBoard(int tr, int tc, int dr, int dc, int size) { if(size == 1) return; int t = tile++, // L型骨牌号 s = size / 2; if(dr<tr+s && dc<tc+s) // 特殊方格在左上角棋盘 ChessBoard(tr, tc, dr, dc, s); else // 左上角棋盘没有特殊方格 { // 用t号L型骨牌覆盖右下角 Board[tr+s-1][tc+s-1] = t; // 覆盖其余方格 ChessBoard(tr, tc, tr+s-1, tc+s-1, s); } if(dr<tr+s && dc>=tc+s) // 特殊方格在右上角棋盘 ChessBoard(tr, tc+s, dr, dc, s) else { Board[tr+s-1][tc+s] = t; ChessBoard(tr, tc+s, tr+s-1, tc+s, s); } if(dr>=tr+s && dc<tc+s) // 特殊方格在左下棋盘 ChessBoard(tr+s, tc, dr, dc); else { Board[tr+s][tc+s-1] = t; ChessBoard(tr+s, tc, tr+s, tc+s-1, s); } if(dr>=tr+s && dc>=tc+s) // 特殊方格在右下棋盘 ChessBoard(tr+s, tc+s, dr, dc, s); else { Board[tr+s][tc+s] = t; ChessBoard(tr+s, tc+s, tr+s, tc+s, s); } }
template<class Type> //递归方法 void MergeSort(Type a[], int left, int right) { if(left<right) { int i = (left+right)/2; MergeSort(a, left, i); MergeSort(a, i+1, right); Merge(a, b, left, i, right); // 合并到数组b Copy(a, b, left, right); // 复制回数组a } } template<class Type> // 合并c[l:m]和c[m+1:r]到d[l:r] void Merge(Type c[], Type d[], int l, int m, int r) { int i = l, j = m+1, k = l; while(i<=m && j<=r) if(c[i]<=c[j]) d[k++] = c[i++]; else d[k++] = c[j++]; if(i>m) for(int q=j, q<=r; q++) d[k++] = c[q]; else for(int q=i; q<=m; q++) d[k++] = c[q]; }
template<class Type> void MergeSort(Type a[], int p, int r) { if(p<r) { int q = Partition(a, p, r); MergeSort(a, p, q-1); MergeSort(a, q, r); } } // 以a[p]为基准,小于的交换到左边区域,大于的交换到右边区域 template<class Type> int Partition(Type a[], int p, int r) { type x = a[p]; int i = p, j = r+1; while(true) { while(a[++i]<x && i<r); while(a[--j]>x); if(i>=j) break; swap(a[i], a[j]); } a[p] = a[j]; a[j] = x; return j; }
template<class Type>
Type RandomizedSelect(Type a[], int p, int r, int k)
{
if(p==r) return a[p];
int i = RandomizedPartition(a, p, r),
j = i-p+1;
if(k<=j)
return RandomizedSelect(a, p, i, k);
else
return RandomizedSelect(a, i+1, r, k-j);
}
void GameTable(int k, int a[][N]) // 数组下标从1开始 { int n = 1; for(int i=1; i<=k; i++) n *= 2; // 求总人数 for(int i=1; i<=n; i++) a[1][i] = i; // 第一行排1-8 int m = 1; // 用来控制每一次填表时i行j列的起始填充位置 for(int s=1; s<=k; s++) // s指对称赋值的总循环次数,即分成几大步进行制作日程表 for(int i=m+1; i<=2*m; i++) for(int j=m+1; j<=2*m; j++) { a[i][j+(t-1)*m*2] = a[i-m][j+(t-1)*m*2-m]; // 右下角等于左上角 a[i][j+(t-1)*m*2-m] = a[i-m][j+(t-1)*m*2]; // 左下角等于右上角 } m *= 2; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。