算法C++

【求未知数租的长度 】

#include<iostream>
#include<vector>//引入vector头文件
using namespace std;
int main()
{
    vector<int> array;//定义一个vector数组的array
    int number;
    while(1){
        cin>>number;
        array.push_back(number);//每输入一个数字就把他添加到数组的最后
        if(cin.get()=='\n') break;//如果是回车符则跳出循环
    }
    int len=array.size();
    for(int i=0;i<len;i++)
    {
        cout<<array[i]<<" ";
    }
    return 0;


}

【费式数列(Fibonacci数列)】

#include<iostream>
using namespace std;
#define N 100
int main()
{
    int F[N];
    F[0]=F[1]=1;
    for(int i=2;i<N;i++){
        F[i]=F[i-1]+F[i-2];
    }
    for(int i=0;i<N;i++){
        cout<<F[i]<<" ";
    }
    return 0;
}

【求最大公因数和最小公倍数】

#include<iostream>
using namespace std;
int main()
{
    int m,n,s,r;
    cin>>m>>n;
    s=m*n;
   while(n!=0){
    r=m%n;
    m=n;
    n=r;
   }
   cout<<"最大公因数为:"<<m<<endl;
   cout<<"最小公倍数为:"<<s/m<<endl;
   return 0;
}

【河内之塔(汉诺塔)】

#include<iostream>
using namespace std;
void hanio(int n,char A,char B,char C){
    if(n==1){
            //如果只有一个,直接从A移动到C即可
        cout<<"Move sheet "<<n<<" from "<<A<<" to "<<C<<endl;
    }
    else{
        //表示先把n-1个圆盘成功从A移动到B
        hanio(n-1,A,C,B);
       //把第n个圆盘从A移动到C
        cout<<"Move sheet "<<n<<" from "<<A<<" to "<<C<<endl;
         //表示把n-1个圆盘再成功从B移动到C
        hanio(n-1,B,A,C);
    }
}
int main()
{
    int m;
    cout<<"请输入盘数:";
    cin>>m;
    hanio(m,'A','B','C');
    return 0;
}

【用递归求解组合问题】

#include<iostream>
#include<stdlib.h>
using namespace std;
int comb(int n,int m);
int main()
{
    int a,b;
    cin>>a>>b;
    cout<<comb(a,b);
     system("pause");//解决vs软件窗口闪退的问题,需要加头文件#include"stdlib.h"
    return 0;
}
int comb(int n,int m){
    if(m==0||n==m){
        return (1);
    }
    else{
        return (comb(n-1,m-1)+comb(n-1,m));
    }
}

【用动态规划求解组合问题】

#include<iostream>
#include<stdlib.h>
using namespace std;
int comb(int n,int m);
int main()
{
    int a,b;
    cin>>a>>b;
    cout<<comb(a,b);
     system("pause");//解决vs软件窗口闪退的问题,需要加头文件#include"stdlib.h"
    return 0;
}
int comb(int n,int m){
    int c[n][m];
    for(int i=0;i<n;i++) c[i][0]=i;
    for(int j=0;j<m;j++) c[0][j]=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(i<j) {
                    c[i][j]=0;
            }
            else if(i==j){
                 c[i][j]=1;
            }
            else {
                c[i][j]=c[i-1][j]+c[i-1][j-1];
            }
        }
    }
}

【线性动态规划 -----合唱队形问题】

分析最优子结构

已知8个学生的身高:176、163、150、180、170、130、167、160,计算他们所组成的最长合唱队形的长度

功能:从n个同学中取出k个,求他们所组成的合唱队形        

输入:队员人数n和每个学生身高a[i]        

输出:最长的合唱队形的长度ans

#include<iostream>
using namespace std;
int main()
{
    int n,ans=0;
    cout<<"请输入合唱团的人数:";
    cin>>n;
    int a[n],f1[100],f2[100];
     cout<<"请输入合唱团每个人的身高:";
    for(int i=0;i<n;i++)
        cin>>a[i];
     for(int i=0;i<n;i++){
        f1[i]=1;
        for(int j=0;j<i;j++)
            if(a[j]<a[i]&&f1[i]<f1[j]+1)
                f1[i]=f1[j]+1;// 从左到右求最大上升子序列
    }
    for(int i=n-1;i>=0;i--){
                f2[i]=1;
            for(int j=i+1;j<n;j++){
                if(a[j]<a[i]&&f2[i]<f2[j]+1)
                    f2[i]=f2[j]+1;//从右到左求最大下降子序列
            }

        }
        for(int i=0;i<n;i++){
            if(ans<f1[i]+f2[i]-1)
                ans=f1[i]+f2[i]-1;//枚举中间最高值
        }
        cout<<"最长合唱队形的长度为:"<<ans;
        return 0;
}
//176 163 150 180 170 130 167 160
#include<iostream>
using namespace std;
int main()
{
    int n,ans=0;
    cout<<"请输入合唱团的人数:";
    cin>>n;
    int a[n+1],f1[100],f2[100];//数组下标从1开始是a[n+1]而不是a[n]
     cout<<"请输入合唱团每个人的身高:";
    for(int i=1;i<=n;i++)
        cin>>a[i];
     for(int i=1;i<=n;i++){
        f1[i]=1;
        for(int j=1;j<i;j++)
            if(a[j]<a[i]&&f1[i]<f1[j]+1)
                f1[i]=f1[j]+1;// 从左到右求最大上升子序列
    }
    for(int i=n;i>=1;i--){
                f2[i]=1;
            for(int j=i+1;j<=n;j++){
                if(a[j]<a[i]&&f2[i]<f2[j]+1)
                    f2[i]=f2[j]+1;//从右到左求最大下降子序列
            }

        }
        for(int i=1;i<=n;i++){
            if(ans<f1[i]+f2[i]-1)
                ans=f1[i]+f2[i]-1;//枚举中间最高值
        }
        cout<<"最长合唱队形的长度为:"<<ans;
        return 0;
}
//176 163 150 180 170 130 167 160
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define N 110
int dp1[N],dp2[N];
int main()
{
    int n;
    scanf("%d",&n);
    int a[n+1],b[n+1];
    int i,j;
    for(i=1;i<=n;i++){
        scanf("%d",&a[i]);
        b[n-i+1]=a[i];//倒序求下降序列
    }
    for(i=1;i<=n;i++){
        dp1[i]=1;
        for(j=1;j<i;j++){
            if(a[j]<a[i]){
                dp1[i]=max(dp1[i],dp1[j]+1);
            }
        }
    }
    for(i=1;i<=n;i++){
        dp2[i]=1;
        for(j=1;j<i;j++){
            if(b[j]<b[i]){
                dp2[i]=max(dp2[i],dp2[j]+1);
            }
        }
    }
    int x=0,ans=0;
    for(i=1;i<=n;i++){
        if(x<dp1[i]+dp2[n-i+1]){//枚举每个点的最大升序列和最大降序列的和
            x=dp1[i]+dp2[n-i+1];
        }
    }
    ans=n-x+1;
    printf("%d\n",ans);
    return 0;

【回溯法】--01背包问题

https://blog.csdn.net/qian2213762498/article/details/79420269?utm_source=app&app_version=4.12.0&code=app_1562916241&uLinkId=usr1mkqgl919blen

#include <iostream>
#include <stdio.h>
using namespace std;
int n;//物品数量
double c;//背包容量
double v[100];//各个物品的价值 value
double w[100];//各个物品的重量 weight
double cw = 0.0;//当前背包重量 current weight
double cp = 0.0;//当前背包中物品总价值 current value
double bestp = 0.0;//当前最优价值best price
double perp[100];//单位物品价值(排序后) per price
int order[100];//物品编号
int put[100];//设置是否装入,为1的时候表示选择该组数据装入,为0的表示不选择该组数据


//按单位价值排序
void knapsack()
{
    int i,j;
    int temporder = 0;
    double temp = 0.0;

    for(i=1;i<=n;i++)
        perp[i]=v[i]/w[i]; //计算单位价值(单位重量的物品价值)
    for(i=1;i<=n-1;i++)
    {
        for(j=i+1;j<=n;j++)
            if(perp[i]<perp[j])//冒泡排序perp[],order[],sortv[],sortw[]
        {
            temp = perp[i];  //冒泡对perp[]排序
            perp[i]=perp[j];
            perp[j]=temp;

            temporder=order[i];//冒泡对order[]排序
            order[i]=order[j];
            order[j]=temporder;

            temp = v[i];//冒泡对v[]排序
            v[i]=v[j];
            v[j]=temp;

            temp=w[i];//冒泡对w[]排序
            w[i]=w[j];
            w[j]=temp;
        }
    }
}

//回溯函数
void backtrack(int i)
{   //i用来指示到达的层数(第几步,从0开始),同时也指示当前选择玩了几个物品
    double bound(int i);
    if((i>n)&&(cp>bestp)) //递归结束的判定条件
    {
        bestp = cp;
        return;
    }
    //如若左子节点可行,则直接搜索左子树;
    //对于右子树,先计算上界函数,以判断是否将其减去
    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)//如若符合条件则搜索右子树
    {
          put[i]=0;
        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)//但我们为了让价值上限尽可能的大,所以89-90行就是为了让不能完整装入的下一个物品装入部分,以获得更大的价值上限,用来估值的,回溯法要剪枝
        b+=v[i]/w[i]*leftw;
    return b;//返回计算出的上界

}



int main()
{
    int i;
    printf("请输入物品的数量和背包的容量:");
    scanf("%d %lf",&n,&c);
    printf("请依次输入%d个物品的重量:\n",n);
    for(i=1;i<=n;i++){
        scanf("%lf",&w[i]);
        order[i]=i;
    }

    printf("请依次输入%d个物品的价值:\n",n);
    for(i=1;i<=n;i++){
        scanf("%lf",&v[i]);
    }


    knapsack();
    backtrack(1);


    printf("最优价值为:%lf\n",bestp);
    printf("需要装入的物品编号是:");
    for(i=1;i<=n;i++)
    {
        if(put[i]==1)
            printf("%d ",order[i]);
    }
    return 0;
}

【运动员最佳配对问题】

 问题描述 :       

设一个羽毛球队有男女运动员各n人,给定2个n*n 矩阵P 和Q, 其中P [i][j]表示男运动员i 和女运动员j 配对组成混合双打时的竞赛优势,Q[i][j]则是女运动员i 和男运动员j 配对组成混合双打时的竞赛优势。由于技术的配合和心理状态等各种因素的影响,一般P[i][j]不一定与Q[j][i]相等。设计一个算法, 计算出男女运动员的最佳配对方法,使各组男女双方竞赛优势乘积的总和达到最大。

#include <bits/stdc++.h>
using namespace std;

int n;
int boy[21][21],girl[21][21];   //分别用于存放男、女运动员的竞赛优势
int Max=INT_MIN;   //Max代表男女双方竞赛优势的总和的最大值
int sum=0;   //sum为临时求和
int data[21][21];   //data[i][]用于存放男运动员 i 配对后的双方竞赛优势
int maxSum[21];   //记录每个男生匹配后可达到的最大双方竞赛优势
int book[21];   //用于标记女运动员是否已匹配:book[0]未匹配;book[1]匹配

void dfs(int t)
{
    if(t>=n)   //t到达n之后,代表全部标记访问了,得到了最大值
    {
        Max=max(Max,sum);
        return ;
    }
    int ctn=0;   //剪枝函数:之前t个已匹配好的男女运动员的sum与之后的 t->n-1 个男匹配女的最大值加起来与已经得到的Max比较,若前者<=Max,剪枝
    for(int i=t;i<n;i++)   //求t及t之后男生匹配女生的最大值的和
        ctn+=maxSum[i];
    if(sum+ctn<Max)   //若从第t组->第n组,当前搜索sum加上假设匹配后的最大值cxn,仍然小于Max ,就需要剪枝了,则Max为已经求得的最大值
        return ;
    for(int i=0;i<n;i++)   //若cxn>=Max,要探索子树。从第t个男生开始匹配,找未匹配的女生
    {
        if(!book[i])   //第 i 个女生未匹配
        {
            book[i]=1;   //第 t 个男生匹配女生i
            sum+=data[t][i];   //加上男生t与女生i的男女双方竞赛优势
            dfs(t+1);   //为第i+1个男生匹配
            book[i]=0;   //若第 t 个男生匹配女生i得到的sum不大于Max,则回溯
            sum-=data[t][i];
        }
    }
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)   //输入男运动员的竞赛优势
    {
        for(int j=0;j<n;j++)
            cin>>boy[i][j];
    }
    for(int i=0;i<n;i++)   //输入女运动员的竞赛优势
    {
        for(int j=0;j<n;j++)
            cin>>girl[i][j];
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            data[i][j]=boy[i][j]*girl[j][i];   //对每个男生都求男女双方竞赛优势,则能得到i*j种结果(涵盖了P[i][j]*Q[j][i]与Q[i][j]*P[j][i])
            maxSum[i]=max(maxSum[i],data[i][j]);   //记录每个男生匹配后可达到的最大双方竞赛优势,用于后面的剪枝
        }

    }
    dfs(0);
    cout<<Max<<endl;
    return 0;
}
//回溯法
#include <iostream>
#include <fstream>
#include <algorithm>
#include <functional>
using namespace std;
class Athletes
{
public:
	Athletes(int n,int *P, int *Q);
	int getBest(){return best;}
	int* getBestx(){return bestx;}
protected:
private:
	int n;//运动员数量
	int best;//最优值
	int *x;//当前解向量
	int *bestx;//最优解向量
	int *P;//男配女优势矩阵
	int *Q;//女配男优势矩阵
	void Backtrace(int t);
	void com();//计算当前排列值
};
Athletes::Athletes(int n,int *P, int *Q){
	this->n = n;
	this->P = P;
	this->Q = Q;
	best = 0;
	x = new int[n + 1];
	bestx = new int[n + 1];
	for (int i = 1; i <= n; ++i)
	{
		x[i] = i;
	}
	Backtrace(1);
}
void Athletes::com(){
	for (int i = 1,temp = 0; i <= n; ++i)
	{
		temp += P[(n+1) * i + x[i]] * Q[x[i] * (n + 1) + i];
	}
	if (temp > best)
	{
		best = temp;
		for (int i = 1; i <= n; ++i)
		{
			bestx[i] = x[i];
		}
	}
}
void Athletes::Backtrace(int t){
	if (t > n)
	{
		this->com();
	}
	else{
		for (int j = t; j <= n; ++j)
		{
			swap(x[t],x[j]);
			Backtrace(t+1);
			swap(x[j],x[t]);
		}
	}
}
int main(){
	ifstream in("input.txt");
	ofstream out("output.txt");
//	#define in cin
//	#define out cout
	int cases;
	in>>cases;
	for(int Case = 1; Case <= cases; ++Case){
		int n;
		in>>n;
		int *P = new int[(n + 1)*(n + 1)];
		int *Q = new int[(n + 1)*(n + 1)];
		for (int i = 1; i <= n; ++i)
		{
			for (int j = 1; j <= n; ++j)
			{
				in>>P[(n + 1) * i + j];
			}
		}
		for ( i = 1; i <= n; ++i)
		{
			for (int j = 1; j <= n; ++j)
			{
				in>>Q[(n + 1) * i + j];
			}
		}
		Athletes match(n,P,Q);
		out<<"Case #"<<Case<<": "<<match.getBest()<<endl;
	}
	return 0;
}
//分支限界法
#include <iostream>
#include <fstream>
#include <algorithm>
#include <functional>
#include <queue>
using namespace std;
int n;
int **P;
int **Q;
class ArgNode{	
public:
	int *arg;//当前男运动员排列
	int t;//arg[1:t]已排列
	int val;//此种排列的竞赛优势值	
public:
	ArgNode(ArgNode const &source){
		arg = new int [n + 1];
		for (int i = 0; i <= n; ++i)
		{
			arg[i] = source.arg[i];
		}
		t = source.t;
		val = source.val;
	}
	ArgNode(int *arg,int t,int val){
		this->arg = new int [n + 1];		
		for (int i = 0; i <= n; i++){
			this->arg[i] = arg[i];
		}
		this->t = t;
		this->val = val;
	};
	//大顶堆
	bool operator <(const ArgNode &other)const{
		if (this->val > other.val)
		{
			return false;
		}
		else return true;
	}
	void compute();//计算当前节点值
};
void ArgNode::compute(){
	val = 0;
	for (int i = 1; i <= this->t; ++i)
	{
		val += P[i][arg[i]] * Q[arg[i]][i];
	}
}
int Athletes(){
	//初始化
	priority_queue<ArgNode> Heap;
	int *iniArr = new int[n + 1];
	int i,best = 0;
	for (i = 0; i <= n; ++i)
	{
		iniArr[i] = i;
	}
	ArgNode *initial = new ArgNode(iniArr,0,0);
	delete iniArr;
	Heap.push(*initial);
	while(!Heap.empty()){
		ArgNode fatherNode = Heap.top();
		Heap.pop();
		if (fatherNode.t == n)//是一个全排列,则比较节点内值是否比当前最优值更佳
		{
			if (best < fatherNode.val)
			{
				best = fatherNode.val;
			}
		}
		else{
			for (i = fatherNode.t + 1; i <= n; ++i)//广度优先所搜子树
			{
				ArgNode newNode(fatherNode);//把子节点内容先复制为父节点内容
				++newNode.t;//深度++
				newNode.arg[newNode.t] = fatherNode.arg[i];//选择第i个女选手
				newNode.arg[i] = fatherNode.arg[newNode.t];
				newNode.compute();//子节点计算val
				Heap.push(newNode);
			}
		}
		
	}
	return best;
}
int main(){
	ifstream in("input.txt");
	ofstream out("output.txt");
#define in cin
#define out cout
	int cases;
	in>>cases;
	for(int Case = 1; Case <= cases; ++Case){
		n;
		in>>n;
		int i,j;
		P = new int *[n + 1];
		Q = new int *[n + 1];
		for (i = 0; i <= n; ++i){
			P[i] = new int[n + 1];
			Q[i] = new int[n + 1];
		}
		for (i = 1;  i<= n; ++i){
			for (j = 1; j <= n; ++j){
				in>>P[i][j];
			}
		}
		for (i = 1;  i<= n; ++i){
			for (j = 1; j <= n; ++j){
				in>>Q[i][j];
			}
		}
		out<<"Case #"<<Case<<": "<<Athletes()<<endl;
		for (i = 0; i <= n; ++i){
			delete P[i];
			delete Q[i];
		}
		delete P;
		delete Q;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值