1.用递归求n个数的全排列
int star[]={0,1,2,3,4,5,6,8,9,10,12}; //储存要排列的n个数,0不用
#define Swap(a,b) {int temp = a; a = b; b = temp;} //交换
int num=0; //统计全排列的个数
int Perm(int begin,int end)//求数组里begin到end的全排列
{
int i;
if(begin == end) // 结束,输出一个全排列
num++; //统计全排列的个数;
else
for(i = begin;i <= end;i++)
{
Swap(star[begin],star[i]);//交换位置,逐步前提
Perm(begin+1,end);
Swap(star[begin],star[i]);//将位置还回去,对下一次排列负责
}
}
求第n个全排列
int num[21] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 };
void change(int i, int j) {
int tmp = num[i];
num[i] = num[j];
num[j] = tmp;
}
bool fun(int begin, int end){
if (begin == end)
m--;
else if (m > 0) {
for (int i = begin; i <= end; i++) {
change(begin, i);
if(fun(begin + 1, end))
return true;
change(begin, i);
}
}
if (m == 0) {
for (int i = 1; i <= n; i++) {
printf("%d", num[i]);
if (i != n) printf(" ");
}
return true;
}
return false;
}
2.双向广度优先搜索
3.回溯算法
4.A算法
5.转数字Hash
用于不好比较的对象,如日期,坐标,字符串等。***本质是N进制的使用***
6.二分法的原理
把时间值转换为二进制,用相应的二进制位的幂来表示十进制数,进而将时间复杂度为十进制的数分解成时间复杂度为二的指数(即n变为log n)
7.0-1背包
DFS+DP+prun
// index 当前处理的物品编号,sumW 和 sumC 为当前总重量和总价值
void DFS(int index, int sumW, int sumC) {
if(index == n) { // 已经把 n 件物品处理完毕(死胡同)
return;
}
// 岔道口
DFS(index+1, sumW, sumC); // 不选 Index 号物品
// 只有加入 index 物品后总重量小于 V 才可以继续
if(sumW + w[index] <= V) {
if(sumC + c[index] > maxValue) {
maxValue = sumC + c[index];
}
DFS(index+1, sumW+w[index], sumC+c[index]); // 选 Index 号物品
}
}
8.枚举N选K的所有方案
int n,k,x,maxSumSqu=-1,a[maxn];//maxSumSqu是最大平方和
vector<int> temp,ans;
void DFS(int index,int nowK,int sum,int sumSqu)
{
if(nowK==K&&sum==X)
{
if(sumSqu>maxSumSqu)
{
maxSumSqu=sumSqu;
ans=temp;
}
return;
}
if(index==n||nowK>K||sum>X)
return;
temp.push_back(a[index]);
DFS(index+1,nowK+1,sum+a[index],sumSqu+a[index]*a[index]);//选择了index
temp.pop_back();//删掉a[index]
DFS(index+1,nowK,sum,sumSqu);//不选index
}
若N个整数中的每一个都可以被选择多次,应将选择了index改为
DFS(index,nowK + 1,sum + A[index],sumSqu + A[index]*A[index]);