【求未知数租的长度 】
#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背包问题
#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;
}