棋盘覆盖
if(dr<tr+s&&dc<tc+s)//覆盖左上角
ChessBoard(tr,tc,dr,dc,s);
else
{
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+s,tc,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,s);
}
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);
}
}
快速排序
#include<iostream>
using namespace std;
const int N=100010;
int q[N];
void quick_sort(int q[],int l,int r){
if(l>=r) return;
int i=l-1,j=r+1,x=q[l+r>>1];
while(i<j){
do i++;while(q[i]<x);
do j--;while(q[j]>x);
if(i<j) swap(q[i],q[j]);
}
quick_sort(q,l,j);
quick_sort(q,j+1,r);
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++) scanf("%d",&q[i]);
quick_sort(q,0,n-1);
for(int i=0;i<n;i++) printf("%d ",q[i]);
return 0;
}
归并排序
#include<iostream>
using namespace std;
const int N=100010;
int q[N],temp[N];
void merge_sort(int q[],int l,int r){
if(l>=r) return;
int mid=l+r>>1;
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
int k=0,i=l,j=mid+1;
while(i<=mid&&j<=r){
if(q[i]<=q[j]) temp[k++]=q[i++];
else temp[k++]=q[j++];
}
while(i<=mid) temp[k++]=q[i++];
while(j<=r) temp[k++]=q[j++];
for(i=l,j=0;i<=r;i++,j++) q[i]=temp[j];
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++) scanf("%d",&q[i]);
merge_sort(q,0,n-1);
for(int i=0;i<n;i++) printf("%d ",q[i]);
return 0;
}
矩阵连乘
原链接:https://www.cnblogs.com/crx234/p/5988453.html
void matrixChain(){
for(int i=1;i<=n;i++) m[i][i]=0;
for(int r=2;r<=n;r++)//对角线循环
for(int i=1;i<=n-r+1;i++){//行循环
int j = r+i-1;//列的控制
//找m[i][j]的最小值,先初始化一下,令k=i
m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];
s[i][j]=i;
//k从i+1到j-1循环找m[i][j]的最小值
for(int k = i+1;k<j;k++){
int temp=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(temp<m[i][j]){
m[i][j]=temp;
//s[][]用来记录在子序列i-j段中,在k位置处
断开能得到最优解
s[i][j]=k;
}
}
}
}
最长公共子序列
链接:https://www.bilibili.com/video/BV1Yp4y1U7Lf?spm_id_from=333.999.0.0
#include <iostream>
using namespace std;
#define N 100
int n,m;
char S1[N],S2[N];
int dp[N][N];
int b[N][N];
void LCSLength()
{
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++){
dp[i][0]=0;
dp[0][j]=0;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(S1[i]==S2[j]){
dp[i][j]=dp[i-1][j-1]+1;
b[i][j]=1;
}
else if(dp[i-1][j]>dp[i][j-1]){
dp[i][j]=dp[i-1][j];
b[i][j]=2;
}
else{
dp[i][j]=dp[i][j-1];
b[i][j]=3;
}
}
}
void LCS(int i,int j)
{
if(i==0||j==0)
return;
if(b[i][j]==1){
LCS(i-1,j-1);
cout<<S1[i]<<" ";//S2[j]
}
else if(b[i][j]==2)
LCS(i-1,j);
else
LCS(i,j-1);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>S1[i];
cin>>m;
for(int i=1;i<=m;i++)
cin>>S2[i];
LCSLength();
cout<<"最长公共子序列长度是:"<<dp[n][m]<<endl;
cout<<"最长公共子序列是:";
LCS(n,m);
cout<<endl;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}
cout<<endl;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
cout<<b[i][j]<<" ";
cout<<endl;
}
}
/*
7
1 5 2 8 9 3 6
6
5 6 8 9 3 7
*/
01背包问题
链接:https://www.bilibili.com/video/BV1g7411B7SP?from=search&seid=10471307089330352864
int f[5][9]={0};//f[k][w]记为背包容量为w,现有k件物品 可偷取的情况下,所能偷的最大值
int w[5]={0,2,3,4,5};
int v[5]={0,3,4,5,8};
int main(){
int i,j;
memset(f,0,sizeof(f*));
for(int i=1;i<5;i++){//i表示4件物品
for(int j=1;j<9;j++){//j表示背包容量
if(w[i]>j)//如果第i件物品的容量比背包容量大就说明装不下
f[i][j]=f[i-1][j];
else //如果第k件物品装的下,取偷和不偷的最大值
f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
}
}
return 0;
}
活动安排问题
链接:https://blog.csdn.net/qq_43424037/article/details/107175891
#include <iostream>
#include <algorithm>
using namespace std;
struct Activity{
int num,start,end,mark;//mark表示活动是否被选择,如果这个活动加入到最优解的序列当中,mark为1。
};
bool comp(Activity a,Activity b)
{
return a.end<b.end;
}
void Select(Activity act[],int n)
{
int begin=act[1].start;//活动1的开始时间
for(int i=1;i<=n;i++)//对以结束时间排列后的活动进行遍历
if(act[i].start>=begin){//如果后一个活动开始时间大于等于begin,这个活动加入到最优解的序列当中
begin=act[i].end;//更新begin为该活动的结束时间
act[i].mark=1;//将这个活动加入到最优解的序列当中并将其标记为1
}
}
int main()
{
int n;
cin>>n;
Activity act[n+1];
for(int i=1;i<=n;i++){
cin>>act[i].start>>act[i].end;
act[i].num=i;
act[i].mark=0;
}
sort(act+1,act+n,comp);//结束时间越早的排在越前面
Select(act,n);//选择
for(int i=1;i<=n;i++)//最后一次遍历,将标志为1的输出
if(act[i].mark==1)
cout<<act[i].num<<" ";
}
/*
测试案例:
11
1 4
3 5
0 6
5 7
3 8
5 9
6 10
8 11
8 12
2 13
12 14
*/
哈夫曼编码
回溯法——0-1背包
int n;
double c;
double v[100];//价值
double w[100];//重量
double cw=0.0//当前背包重量
double cp=0.0//当前背包中物品总价值
double bestp;//当前最优价值
double perp[100];//排序后单位物品价值
int order[100];//物品编号
int put[100];//设置是否装入,1表示装入,0表示不选择该组数据
//按单位价值排序
void knapsack(){}
//回溯算法
void backtrack(int i){//i表示达到的层数,同时也值当前选择玩了几个物品
if(cw+w[i]<=c){//将物品i放入背包,搜索左子树
cw+=w[i];//同步更新当前背包的重量
cp+=v[i];//同步更新当前背包的总价值
put[i]=1;
backtrack(i+1);//深度搜索进入下一层
cw-=w[i];//回溯复原
cp-=v[i];//回溯复原
}
if(bound(i+1)>bestp){//如若符合条件则搜索右子树
backtrack(i+1);
}
}
//计算上界函数,功能为剪枝
double bound(int i)
{ //判断当前背包的总价值cp+剩余容量可容纳的最大价值<=当前最优价值
double leftw= c-cw;//剩余背包容量
double b = cp;//记录当前背包的总价值cp,最后求上界
//以物品单位重量价值递减次序装入物品
while(i<=n && w[i]<=leftw)
{
leftw-=w[i];
b+=v[i];
i++;
}
//装满背包
if(i<=n)
b+=v[i]/w[i]*leftw;
return b;//返回计算出的上界
}
回溯法——n后问题
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namesapce std;
int n;
int x[20];
int place(int k){
int i;
for(int i=0;i<k;i++){
if(abs(k-1)==abs(x[k]-x[i])||x[k]==x[i]) return 0;
return 1;
}
}
int queen(){
int i;
x[1]=0;
int t=1;
int sum=0;
while(t>0){
x[t]+=1;
while(x[t]<=n&&!place(t))
x[t]++;
if(x[t]<=n)
if(t==n){
sum++;
for(i=1;i<=n;i++) printf("%d",x[i]);
printf("\n");
}else{
x[++t]=0;
}
else t--;
}
return sum;
}
int main(){
int t;
printf("请输入要防止的皇后的个数:");
scanf("%d",&n);
t=queen();
printf("共有%d个解\n",t);
return 0;
}
回溯法——旅行商问题
分支限界——单原点最短路径
ypep Knap::MaxKnapsack()
H = new MaxHeap(1000);
bestx = new int [n+1];
//初始化,为处理子集树中的第一层做准备,物品i处于子集树中的第i层
int i = 1; //生成子集树中的第一层的结点
E = 0; //将首个扩展点设置为null,也就是物品1的父节点
cw = 0;
cp = 0;
Typep bestp = 0; //当前最优值
Typep up = Bound(1); // 选取物品1之后的价值上界
//当选择左儿子结点时,上界约束up不用关心,重量约束wt需要考虑。因为上界约束跟父节点相同。
//当选择右儿子结点时,上界约束up需要考虑,重量约束不需要考虑。因为父节点和该结点重量相同。
while (i != n+1)
{
//检查当前扩展结点的左儿子结点
Typew wt = cw + w[i]; //当前选择物品i之后的总重量wt
if(wt <= c) //背包能将物品i装下,也即当前扩展结点的左儿子结点可行
{
if(cp + p[i] > bestp)
bestp = cp + p[i];
AddLiveNode(up, cp + p[i], cw + w[i], 1, i);
}
//检查当前扩展结点的右儿子结点
up = Bound(i + 1); //未选择物品i之后的价值上界
if(up >= bestp)
AddLiveNode(up, cp, cw, 0, i);
//从优先队列中选择价值上界最大的结点成为扩展结点
HeapNode* N;
H->DeleteMax(N);
E = N->elemPtr;
cw = N->weight;
cp = N->profit;
up = N->uprofit;
i = N->level + 1; //准备生成N.level+1层的子集树结点
}
//从子集树中的某叶子结点开始构造当前最优解
for (int i = n; i > 0; i--)
{
bestx[i] = E->LChild;
E = E->parent;
}
return cp;
}