算法-递归

例子1 全排列 n!

#include <iostream>
using namespace std;
void swap(int& a,int& b){
    int r=a;
    a = b;
    b=r;
}
//将数组 第begin个数到第end个数之间的数进行全排列输出 
void permutation(int* list,int begin, int end){
    if(begin==end){  //第end个数已经排好 可以输出了 
        for(int i=0;i<end;i++){
            cout<<list[i]<<",";
        }
        cout<<endl;
        return;
    }
    for(int i=begin;i<end;i++){
        swap(list[begin],list[i]);
        permutation(list,begin+1,end);
        swap(list[i],list[begin]);  //恢复数组原样 
    }
}

int main(){
    int n;
    int list[10]={1,2,3,4,5,6,7,8,9,0};
    cin>>n;
    permutation(list,0,n);
    for(int i=0;i<10;i++){
        cout<<list[i]<<" ";
    }
}

例子2:逆波兰表达式

#include <iostream>
using namespace std;

//逆波兰表达式 
double exp(){
    char r[10];
    scanf("%s",r);  //遇空格断开 
    switch(r[0]){
        case '+': return exp() + exp();
        case '-': return exp() - exp();
        case '*': return exp() * exp();
        case '/': return exp() / exp();
        default: return atof(r);
    }
}


int main(){
double ans;
ans = exp();
cout<<ans;
}
#include <iostream>
using namespace std;

//逆波兰表达式 转化为普通表达式 
void exp(){
    char r[10];
    scanf("%s",r);  //遇空格断开 
    switch(r[0]){
        case '+': cout<<"(";exp();cout<<"+";exp();cout<<")"; break;
        case '-': cout<<"(";exp();cout<<"-";exp();cout<<")"; break;
        case '*': cout<<"(";exp();cout<<"*";exp();cout<<")";break;
        case '/': cout<<"(";exp();cout<<"/";exp();cout<<")";break;
        default: cout<<r;
    }
}


int main(){
exp();
}

例子3 普通表达式的计算

#include <iostream>
using namespace std;
//表达式的常规计算
//基本思想 : 表达式由项组成(以+或-连接起来的不同部分) 
//项由因子组成(以*或/连接起来的不同部分)
//因子又是由数字或表达式组成的,表达式由括号扩着 
//数字和数字之间可以直接计算

double expValue();
double factorValue(){
    //读入并计算一个因子的值
    double v;
    char c = cin.peek();
    if(c=='('){  //在括号里面说明是表达式 
        cin.get();
        v = expValue(); 
        cin.get();
    }
    else{
        cin>>v;
    }
    return v;
}

double itemValue(){
    //读入并计算项的值
    double v=factorValue();
    while(1){  
        char c=cin.peek();
        if(c=='/'){
            cin.get();
            v /= factorValue();
        }
        else if(c=='*'){
            cin.get();
            v *= factorValue();
        }
        else{
            break;
        }
    } 
    return v;
}

double expValue(){
    //计算表达式的值
    double v=itemValue();
    while(1){  //重复提取计算符号和表达式 
        char c= cin.peek();
        if(c=='+'){
            cin.get();
            v += itemValue();
        }
        else if(c=='-'){
            cin.get();
            v -= itemValue();
        }
        else{
            break;
        }
    } 
    return v;
} 

int main(){
    cout<<expValue()<<endl;
}

例子4:分割棋盘

#include <iostream>
#include <cmath>
#include <cstring>
#include <iomanip>
using namespace std;

//棋盘分割  每个棋格都代表一个数
//用一刀切法 切割指定次数 分割给定的正方形棋盘 ,分成的矩形小棋盘的值是其所有格子之和
//求使得各矩形小棋盘总分的均方差最小值
//分析问题 大棋盘是给定的,n也是给定的 所以无论怎么分 分成的矩形小棋盘总分的均值总是相同的
//各矩形小棋盘只由 各个小棋盘的总分平方和决定
//因此问题转化为 求将一个给定的棋盘分成指定个矩形,矩形的总分的平方和最小为多少。

//给每个格子(x,y)坐标
int sum[9][9];//sum(i,j)是棋盘(1,1)到(i,j)的总分
int result[16][9][9][9][9];//result(n,x1,y1,x2,y2)是将(x1,y1)和(x2,y2)构成的矩形分成n块,的最小值
int smallsum(int x1,int y1,int x2,int y2){  //(x1,y1)到(x2,y2)的总分
    return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];
}

int fun(int n,int x1,int y1,int x2,int y2){
    //以(x1,y1)为左定点,(x2,y2)为右定点的矩形,分成n个矩形后 最小的平方和
    //中止条件 横向最多切 x2-x1 , 纵向最多y2-y1, 必须切n-1,所以x2-x1+y2-y1>=n-1
    int v = 1<<30;
        if(n==1){
        int t=smallsum(x1,y1,x2,y2);
        return t*t;
        }

    if(x2-x1+y2-y1<n-1){
        return v;
    }
        if(result[n][x1][y1][x2][y2]!=-1){
         return result[n][x1][y1][x2][y2];
  }
         

    //对 x1-x2之间所有能切的的切法进行遍历
    for(int x=x1;x<x2;x++){
        int left=smallsum(x1,y1,x,y2);
        int right=smallsum(x+1,y1,x2,y2);
        int t=min(fun(n-1,x+1,y1,x2,y2)+left*left,fun(n-1,x1,y1,x,y2)+right*right);
        v = min(v,t);
    }
    //对y1-y2之间所有能切的切法进行遍历
    for(int y=y1;y<y2;y++){
        int up=smallsum(x1,y1,x2,y);
        int down=smallsum(x1,y+1,x2,y2);
        int t=min(fun(n-1,x1,y1,x2,y)+down*down,fun(n-1,x1,y+1,x2,y2));
        v = min(v,t);
    }
    result[n][x1][y1][x2][y2] = v;
    return v;
}
 
int main(){
    int n;
    memset(sum,0,sizeof(sum));//置0
    memset(result,0xff,sizeof(result));//置-1
    cin>>n;
    for(int i=1;i<=8;i++){
        int rowsum = 0;
            for(int j=1;j<=8;j++){
                int s;
                cin>>s;
                rowsum +=s;
                sum[i][j]=sum[i-1][j]+rowsum; //上一行以上的矩形+ 本行的矩形
            }
       
    }
    //输出均方差
     int squareSum = fun(n,1,1,8,8);
     double result = n*squareSum - sum[8][8]*sum[8][8];
     cout<<setiosflags(ios::fixed) << setprecision(3) <<sqrt(result/(n*n));
}

例5.放苹果问题

#include <iostream>
#include <cmath>
#include <cstring>
#include <iomanip>
using namespace std;

//放苹果问题  将m个苹果放到n个盘子里,允许有的盘子空着不放 
int appway(int m,int n){
    if(m==0){
        return 1;
    }
    if(n==0){
        return 0;
    }
    if(n>m){
        return appway(m,m);
    }
    //下面处理盘子数目小于等于苹果数的情况
    return  appway(m,n-1)+appway(m-n,n);
}
int main(){
    int m,n;
    cin>>m>>n;
    cout<<appway(m,n);
}

 

posted @ 2018-05-21 17:24  Latticeeee  阅读(176)  评论(0编辑  收藏  举报