算法分析与设计实验题目

棋盘覆盖

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;
 
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值