//产生从元素k~m的全排列,作为前k—1个元素的后缀
void Perm(int list[], int k, int m)
{
if(k==m) //构成了一次全排列,输出结果
{
for(int i=0;i<=m;i++)
cout<<list[i]<<" ";
cout<<endl;
}
else
//在数组list中,产生从元素k~m的全排列
for(int j=k;j<=m;j++)
{
swap(list[k],list[j]);
Perm(list,k+1,m);
swap(list[k],list[j]);
}
}
整数划分问题
int split(int n,int m)
{
if(n==1||m==1) return 1;
else if (n<m) return split(n,n);
else if(n==m) return split(n,n-1)+1;
else return split(n,m-1)+split(n-m,m);
}
分治策略的算法设计模式
Divide_and_Conquer(P)
{
if (|P|<=n0 ) return adhoc(P);
divide P into smaller substances P1,P2,…,Pk;
for (i=1; i<=k; k++)
yi=Divide-and-Conquer(Pi) //递归解决Pi
Return merge(y1,y2,…,yk) //合并子问题
}
二分搜索算法
//数组a[]中有n个元素,已经按升序排序,待查找的元素x
template<class Type>
int BinarySearch(Type a[],const Type& x,int n)
{
int left=0; //左边界
int right=n-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
}
循环赛日程表
void Table(int k)
{
int i, r;
int n = 1 << k;
//构造正方形表格的第一行数据
for (i=0; i<n; i++)
a[0][i] = i + 1;
//采用分治算法,构造整个循环赛日程表
for (r=1; r<n; r<<=1)
for (i=0; i<n; i+=2*r)
{
Copy(r, r + i, 0, i, r); //①
Copy(r, i, 0, r + i, r); //②
}
}
//源方阵的左上角顶点坐标(fromx, fromy),行列数为r
//目标方阵的左上角顶点坐标(tox, toy),行列数为r
void Copy(int tox, int toy, int fromx, int fromy, int r)
{
for (int i=0; i<r; i++)
for (int j=0; j<r; j++)
a[tox+i][toy+j] = a[fromx+i][fromy+j];
}
选择问题
输油管道问题
半数集问题
整数因子分解
取余运算
回溯
最优装载问题
void Backtrack(int t)
{
if (t > n)
{
if (cw > bestw)
{
for (int i = 1; i <= n; i++)
best[i] = x[i];
bestw = cw;
}
return;
}
r -= w[t];
if (cw + w[t] <= c)
{
x[t] = 1;
cw += w[t];
Backtrack(t + 1);
cw -= w[t];
}
if (cw + r > bestw)
{
w[t] = 0;
Backtrack(t + 1);
}
r += w[t];
}
01背包
void Backtrack(int t)
{
if (t + 1 > n)
{
bestv = cv;
return;
}
if (cw + Q[i].w <= c)
{
cw += Q[i].w;
cv += Q[i].v;
Backtrack(t + 1);
cw -= Q[i].w;
cv -= Q[i].v;
}
if (bound(i + 1) > bestv)
{
Backtrack(t + 1);
}
}
int bound(int i)
{
int cleft = c - cw;
int b = cv;
while (i < n && Q[i].w <= cleft)
{
cleft -= Q[i].w;
b += Q[i].v;
i++;
}
if (i < n)b += cleft * Q[i].d;
return b;
}
子集树模板
void Backtrack(int t)
{
if (t > n)update(x);
else {
for (int i = 0; i <= 1; i++)
{
x[t] = i;
if (constraint(t) && bound(t)) Backtrack(t + 1);
}
}
}
排列树模板
void Backtrack(int t)
{
if (t > n)update(x);
else {
for (int i = t; i <= n; i++)
{
swap(x[t], x[i]);
Backtrack(t + 1);
swap(x[t], x[i]);
}
}
}
m着色
void Backtrack(int t)
{
if (t > n)
{
sum++;
for (int i = 1; i <= n; i++)
printf("%d ", x[i]);
printf("/n");
}
else {
for (int i = 1; i <= m; i++)
{
x[t] = 1;
if(Same(t))Backtrack(t + 1);
x[t] = 0;
}
}
}
bool Same(int t)
{
for (int i = 1; i <= n; i++)
{
if ((x[t][i] == 1) && (x[i] == x[t])) return false;
}
return true;
}
n皇后
void Backtrack(int t)
{
if (t > n)
{
sum++;
for (int i = 1; i <= n; i++)
printf("%d", x[i]);
printf("\n");
}
else {
for (int i = i; i <= n; i++)
{
x[t] = i;
if (Place(t)) Backtrack(t + 1);
}
}
}
inline bool Place(int t)
{
for (int i = 1; i <= t; i++)
{
if((abs(t-i)==abs(x[i] - x[t])||(x[i]==x[t]))
return false;
}
return true;
}