算法竞赛宝典-递归算法

/*P1498 南蛮图腾
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;

int n;
char a[5][5],b[3000+10][3000+10];

int main()
{
    cin>>n;
    memset(a,' ',sizeof(a));
    memset(b,' ',sizeof(b));
}*/


/*P1049 装箱问题
#include <iostream>
using namespace std;

int a[30+1];

int main()
{
    int n,m;
    cin>>m>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }

    return 0;
}*/




/*P1885 Moo(错误)
#include <iostream>
#include <cstring>
using namespace std;

int n,len=0;
string a;
string f(int k);
int Len(int k);

int main()
{
    cin>>n;
    f(n);
    Len(n);
    cout<<a[len-1]<<endl;
    return 0;
}


int Len(int k)
{
    if(len>=n)
        return len;
    else {
        if(k==0) len=3;
        else
        {
            len=2*Len(k-1)+1+k+2;
        }
    }
}


string f(int k)
{
    if(k==0) return a="moo";
    else{
        string b="moo";
        for(int i=1;i<=k;i++)
        {
            b=b+"o";
        }
        return a=f(k-1)+b+f(k-1);
    }
}



*/



/*P1464 Function(有bug,没找到)
#include <iostream>
#include <cstring>
using namespace std;
#define ll long long int

ll w(ll a,ll b,ll c);
ll x[25][25][25];

int main()
{
    ll a,b,c;
    while(cin>>a>>b>>c)
    {
        if(a==-1&&b==-1&&c==-1) break;
        memset(x,0,sizeof(x));
        if(a>20) a=21;
        if(b>20) b=21;
        if(c>20) c=21;
        cout<<"w("<<a<<", "<<b<<", "<<c<<") = "<< w(a,b,c)<<endl;
    }
    return 0;
}
ll w(ll a,ll b,ll c)
{

    if(a<=0||b<=0||c<=0) return 1;
    else if(x[a][b][c]!=0) return x[a][b][c];
    else if(a>20||b>20||c>20) return x[a][b][c]=w(20,20,20);
    else if(a<b&&b<c) return x[a][b][c]=w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
    else return x[a][b][c]=w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1);
}*/



/*P1657 选书
#include <iostream>
using namespace std;

int n,total=0;
int a[100][3];
int b[100];
void f(int x);

int main()
{
    cin>>n;
    if(n==0) cout<<0<<endl;
    else{
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=2;j++)
            {
                cin>>a[i][j];
                b[a[i][j]]=0;
            }
        }
        f(1);
        cout<<total<<endl;
    }
    return 0;
}

void f(int x)
{
    if(x==n+1)
        total++;
    else{
        for(int j=1;j<=2;j++)
        {
            if(b[a[x][j]]==0)
            {
                b[a[x][j]]=1;
                f(x+1);
                b[a[x][j]]=0;
            }
        }
    }
}
*/


/*传球游戏
#include <iostream>
using namespace std;

int n,m,sum=     0;
void f(int k,int step);

int main()
{
    cin>>n>>m;
    f(1,0);
    cout<<sum<<endl;
    return 0;
}

void f(int k,int step)
{
    if(step==m)
    {
        if(k==1) sum++;
    }
    else {
        if(k==1)
        {
            f(k+1,step+1);
            f(n,step+1);
        }
        else if(k==n)
        {
            f(n-1,step+1);
            f(1,step+1);
        }
        else{
            f(k+1,step+1);
            f(k-1,step+1);
        }
    }
}
*/



/*油桶问题
#include <iostream>
using namespace std;

int n,m;
int a[1000+10];
bool f(int n,int m);

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    if(f(n,m)==1) cout<<"yes"<<endl;
    else cout<<"no"<<endl;
    return 0;
}

bool f(int n,int m)
{
    if(a[n]==m)
        return 1;
    else{
        if(f(n-1,m-a[n])==1)
        {
            return 1;
        }
        if(f(n-1,m)==1)
        {
            return 1;
        }
    }
    return 0;
}
*/



/*数字三角形的递归算法
#include <iostream>
#include <cstring>
using namespace std;

int n;
int a[1000+10][1000+10];
int f(int x,int y);

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            a[i][j]=0;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            cin>>a[i][j];
        }
    }
    cout<<f(1,1)<<endl;;
    return 0;
}

int f(int x,int y)
{
    int left,right;
    if(x==n)
        return a[x][y];
    left=f(x+1,y);
    right=f(x+1,y+1);
    if(left>right)
        return left+a[x][y];
    else
        return right+a[x][y];
}

*/





/*求子集的位运算法
#include <iostream>
using namespace std;

int n;
void f(int n);

int main()
{
    cin>>n;
    cout<<"()"<<endl;
    for(int i=1;i<(1<<n);i++)
    {
        f(i);
    }
    return 0;
}

void f(int n)
{
    cout<<"(";
    for(int i=0;i<n;i++)
    {
        if((1<<i)&n)
        {
            cout<<char(i+'a')<<" ";
        }
    }
    cout<<")"<<endl;
}
*/



/*求子集的递归算法
#include <iostream>
using namespace std;

int n;
int a[100+10];
void f(int k);

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        a[i]=-1;
    }
    f(1);
    return 0;
}

void f(int k)
{
    for(int i=0;i<=1;i++)
    {
        a[k]=i;
        if(k==n)
        {
            cout<<"(";
            for(int i=1;i<=n;i++)
            {
                if(a[i]==1)
                    cout<<char('a'+i-1)<<" ";
            }
            cout<<")"<<endl;
        }
        else f(k+1);
    }
}
*/





/*n皇后求摆法数的位运算法
#include <iostream>
using namespace std;

int lim,sum;

void test(int row,int left,int right)
{
    int pos,p;
    if(row!=lim)
    {
        pos=lim&~(row|left|right);
        while(pos!=0)
        {
            p=pos&-pos;
            pos=pos-p;
            test(row+p,(left+p)<<1,(right+p)>>1);
        }
    }
    else sum++;
}

int main()
{
    int n;
    cin>>n;
    lim=(1<<n)-1;//n个1
    test(0,0,0);
    cout<<sum<<endl;
    return 0;
}*/



/*位运算测试
#include <iostream>
using namespace std;
int main()
{
    int a=-10;
    cout<<(~a)<<endl;


    int a[10];
    for(int i=1;i<=5;i++)
    {
        cin>>a[i];
    }
    int sum=0;
    for(int i=1;i<=5;i++)
    {
        sum=(sum^a[i]^a[i]);
    }
    int x=5;
    cout<<(x^sum)<<endl;
    return 0;
}*/



/*
位运算法
    二进制的进位规则:逢二进一
    二进制的借位规则:借一当二
    二进制加法
    二进制减法

    原码:第一位上面是零表示正数,第一位上面是一表示负数
    反码:正数和原码相同,负数是原码除第一位之外其它位都按位取反
    补码:正数和原码相同,负数是补码加一

    补码的加减法

    位运算符:~,&<<>>,|^(按优先级排列)
    位运算符的优先性很低,必须加括号

    按位与运算符:&
        如果两个相应的位都为1,则该位的结果值为1,否则为0
        0&0=0;0&1=0;1&0=0;1&1=1;
        按位与运算通常用于二进制取位操作
        一个数&1的结果就是取二进制的最末位,可以用来判断一个整数的奇偶

    按位或运算符:|
        如果两个相应的位有一个为1,则该位的结果值为1,否则为0
        0|0=0;0|1=1;1|0=1;1|1=1;
        按位或运算通常用于二进制特定位上的无条件赋值
        一个数|1的结果就是把二进制最末尾强行变为一,一个数|1之后再减1就可以把这个数变成最接近原数的偶数

    异或运算符:^
        如果两个相应的位同号,则该位的结果值为0,否则为1
        0^0=0;0^1=1;1^0=1;1^1=0;
        两次异或同一个数最后结果不变,异或运算可以用于简单的加密
        异或可以交换两个整数(局限性极大)
        相同数字异或结果为0,0异或任何数就等于任何数

    取反运算符:~
        所有位都取反,1变成0,0变成1
        正数a变负数,无符号型变成-a,有符号型变成-a-1
        负数b变正数,无符号型无负数,有符号型变成-b-1

    左移运算符:<<
        A<<B,表示所有的二进制位整体向左移动b位,后面B位用0补充
        a<<1,相当于a*2

    右移运算符:>>
        A>>B,表示所有的二进制位整体向右移动b位,前面B位用0补充
        a>>1,相当于a/2
        只能用于正数

*/



/*n皇后问题
abs是求整型数据绝对值的函数,头文件是math.h,stdlib.h
fab是求浮点型数绝对值的函数,头文件是math.h
#include <iostream>
#include <cstdlib>
#include <cstdlib>
using namespace std;

int n,a[20];
int Try(int x,int y);
void f(int x);

int main()
{
    cin>>n;
    f(1);
    return 0;
}
void f(int x)
{
    int y;
    if(x>n)
    {
        for(int i=1;i<=n;i++)
        {
            cout<<a[i];
        }
        cout<<endl;
    }
    else {
        for(y=1;y<=n;y++)
        {
            if(Try(x,y)==1)
            {
                a[x]=y;
                f(x+1);
            }
        }
    }
}


int Try(int x,int y)
{
    int i;
    for(i=1;i<x;i++)
    {
        if(a[i]==y||((abs(i-x))==abs(a[i]-y)))
        {
            break;
        }
    }
    if(i>=x) return 1;
    else return 0;
}
*/





/*分形图2(有错误,未解决)
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

int n;
char a[10][10];
char b[1000+10][1000+10];
void f(int k,int x,int y);

int main()
{
    while(cin>>n)
    {
        if(n==0||n==EOF) break;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                cin>>a[i][j];
            }
        }
        int m;
        cin>>m;
        int len=pow(n*1.0,m);
        for(int i=1;i<=len;i++)
        {
            for(int j=1;j<=len;j++)
            {
                b[i][j]=' ';
            }
        }
        f(m,1,1);
        for(int i=1;i<=len;i++)
        {
            for(int j=1;j<=len;j++)
            {
                cout<<b[i][j];
            }
        }
    }
    return 0;
}
void f(int k,int x,int y)
{
    if(k==1)
    {
        for(int i=x+0;i<n+x;i++)
        {
            for(int j=y+0;j<n+y;j++)
            {
                b[i][j]=a[i-x+1][j-y+1];
            }
        }
    }
    else{
        int sum=1;
        int kk=k-2;
        while(kk--)
            sum=sum*n;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(a[i][j]!=' ')
                {
                    f(k-1,x+sum*n*i,y+sum*n*j);
                }
            }
        }
    }
}*/




/*pow函数
文件:math.h/cmath(C++中)
功能:计算x的y次幂。
返回值:x不能为负数且y为小数,或者x为0且y小于等于0,返回幂指数的结果。
返回类型:double型,int,float会给与警告!*/

/*分形图
#include <iostream>
#include <cmath>
using namespace std;

int n,m;
char a[1000+10][1000+10];

void f(int n,int x,int y);

int main()
{
    while(cin>>n)
    {
        if(n==-1) break;

        m=pow(3.0,n-1);

        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=m;j++)
            {
                a[i][j]=' ';
            }
        }

        f(n,1,1);

        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cout<<a[i][j];
            }
            cout<<endl;
        }

        cout<<"-"<<endl;
    }
    return 0;
}

void f(int n,int x,int y)
{
    int z;
    if(n==1)
        a[x][y]='x';
    else{
        z=pow(3.0,n-2);
        f(n-1,x,y);
        f(n-1,x,y+2*z);
        f(n-1,x+z,y+z);
        f(n-1,x+2*z,y);
        f(n-1,x+2*z,y+2*z);
    }
}
*/





/*拆分自然数的回溯算法
#include <iostream>
using namespace std;

int n,total=0;
int num[100]={0};
void f(int n,int k);

int main()
{
    cin>>n;
    f(n,1);
    cout<<total<<endl;
    return 0;
}


void f(int n,int k)
{
    int x;
    for(int i=1;i<=n;i++)
    {
        if(i>=num[k-1])
        {
            num[k]=i;
            x=n-i;
            if(x==0&&k>1)
            {
                cout<<n<<"="<<num[1];
                for(int i=2;i<=k;i++)
                {
                    cout<<"+"<<num[i];
                }
                cout<<endl;
                total++;
            }
            else
                f(x,k+1);
            num[k]=0;
        }
    }
}*/



/*对于某个问题一时无法下手时,
可以通过一些简单的实例进行分析
以寻找规律*/
/*回溯法*/
/*拆分自然数的递归算法
#include <iostream>
using namespace std;

int num[100],count=0;
void f(int k,int n);

int main()
{
    cin>>num[0];
    for(int i=1;i<=num[0]/2;i++)
    {
        num[1]=i;
        f(1,num[0]-num[1]);
    }
    cout<<count<<endl;
    return 0;
}
void f(int k,int n)
{
    if(n<1)
    {
        cout<<num[0]<<"="<<num[1];
        for(int i=2;i<=k;i++)
            cout<<"+"<<num[i];
        cout<<endl;
        count++;
    }
    else
    {
        for(int i=num[k];i<=n;i++)//存疑,倒过来怎么算
        {
            if(i>=num[k]){
                num[k+1]=i;
                f(k+1,n-num[k+1]);
            }
            if(i<=n){
                num[k+1]=i;
                f(k+1,n-num[k+1]);
            }
        }
    }
}
*/





/*地盘划分的优化递归算法
#include <iostream>
using namespace std;

int sum=0;
int f1(int x,int y);
int f2(int x,int y);

int main()
{
    int x,y;
    cin>>x>>y;
    f1(x,y);
    cout<<sum<<endl;
    cout<<f2(x,y)<<endl;
    return 0;
}

int f2(int x,int y)
{
    if(x>y)
    {
        int t=x;
        x=y;
        y=t;
    }
    if(y%x==0) return y/x;
    else
    {
        int a=x;
        int b=y;
        y=y%x;
        return f2(x,y)+b/a;
    }
}


int f1(int x,int y)
{
    if(x>y)
    {
        int t=y;
        y=x;
        x=t;
    }
    if(y%x==0) return sum=sum+y/x;
    else {
        sum=sum+y/x;
        x=x;
        y=y%x;
        f1(x,y);
    }
}*/



/*地盘划分的朴素递归算法
#include <iostream>
using namespace std;

int sum=0;
int f(int x,int y);

int main()
{
    int x,y;
    cin>>x>>y;
    f(x,y);
    cout<<sum<<endl;
    return 0;
}

int f(int x,int y)
{
    if(x==y) return sum++;
    else
    {
        if(x>y)
        {
            x=x-y;
            sum++;
            f(x,y);
        }
        else
        {
            y=y-x;
            sum++;
            f(x,y);
        }
        return sum;
    }
}
*/



/*棋子移动
#include <iostream>
using namespace std;

int f(int n);

int main()
{
    int n;
    cin>>n;
    f(n);
    return 0;
}
int f(int n)
{
    if(n==4)
    {
        cout<<"4,5-->9,10"<<endl;
        cout<<"8,9-->4,5"<<endl;
        cout<<"2,3-->8,9"<<endl;
        cout<<"7,8-->2,3"<<endl;
        cout<<"1,2-->7,8"<<endl;
    }
    else
    {
        cout<<n<<","<<n+1<<"-->"<<2*n+1<<","<<2*n+2<<endl;
        cout<<2*n-1<<","<<2*n<<"-->"<<n<<","<<n+1<<endl;
        f(n-1);
    }
}*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值