ICPC入门尝试第一篇总结

第一个要总结的就是递归。递归简单来说就是自己调用自己,一直循环下去,直到找到出口后跳出。

在这举一个例子,比如n的阶乘,在之前你没学过递归的话,可能你会用for循环进行累乘。这个用递归也可以写出,而且要比for循环简介很多。首先我们来想一下,

的阶乘是从1一直乘到n,n的阶乘我们可以写成n*n-1的阶乘,n-1的阶乘又可以写成n-1*n-2的阶乘,以此类推,最后变成2乘1。

由此我们可以写一个出口就是当x=1时跳出;此时我们就可以写一个函数F(n)=F(n-1)*n;如下:

int F(int x){
    if(x==1) return 1;
else return F(n-1)*n;
}

如此简单的代码就可以代替for循环。然后在在主函数里输入x的值并调用函数即可。

再有一个典型的例子就是斐波那契数列,这两个可以说是递归里简单的两个例子了。

这里再讲一个n皇后的例子吧。在n*n的国际象棋盘上放置n(n<13)个皇后,使得他们不在同列,同一行,甚至不在同一条斜线上,问有几种放法。

首先我们来想一想最最最常规的办法就是枚举所有的排列方式,在判断其符不符合不在同意斜线的条件。这样的话也是可以的,但如果是有时间限制的话肯定会超时的。

接下来我们想第一个皇后就放在第一行,这是我们只要考虑将他放在第几列即可,再放入列的前提是,斜线也不能冲突,此时只要我们再加一个条件即可。在坐标系里我们可以发现,在同一斜线上的皇后其横纵坐标加起来或相减总是一个常数,因此我们便可以利用这一点来进行判断。我们思路有了,便可以来进行代码编写

#define maxn 100
int a[maxn],b1[maxn],b2[maxn],b3[maxn];//后三个分别记录列和两条斜线
void hh(int x){
    if(x>n) {
        ans++;//如果所有的皇后都有位置了,呢么答案加一
        return;//这里返回到上一层递归;
}
    for(int i=1;i<=n;i++)//第x个皇后放在第几列;
        if(b1[i]==0&&b2[x+i]==0&&b3[x-i+15]==0){//x-i可能为负值我们加上一个数变成正值
            a[x]=1;
            b1[1]=1;b2[x+1]=1;b3[x-i+15]=1;//占位表示该位置有皇后了
            hh(x+1);//下一层递归放下一个皇后
            b1[i]=0;b2[x+i]=0;b3[x-i+15]=0;//复位
}

此后我们只要加上头文件并在主函数里调用函数并输出即可。

递归常用在你可以把大问几个小文题,小问题再分,分到最后可以直接求出答案的。递归在程序设计中很是常见。

   接下来总结一个two pointers思想,在大一上学期期末考试中,老师在最后一个题可以用到这个思想,但当时的我没有做出来,老师当时提供了一个二分的思想,可我当时还是太弱了,没有做出来。加下来让我们看一下呢个题吧。

给定一个递增的正整数序列和一个正整数M,求数列中的两个不同位置的数,使他们的和恰好等于M并输出。

当时我想到的是套用两层for循环,结果不出所料,超时了,果然最后一道题不可能轻轻松松让你过。当看到老师的提示后,开始想二分,但最后还是没能做出来。直到我看到这个思想,原来这个太简单了吧。

首先这是一个有序的数列,我们先i加最后一个元素j来与M进行比较,接下来将有三种情况:

1、和等于M,此时对于i下一个元素加j和j前一个元素加i都不会再等于M,于是我们便将两个元素都向前移一位,再来判断其与M的大小。

2、大于M,如果大于M,呢我们就要想办法减小他,所以只能将j向前移一位。

3、小于M,与大于M相似,将i向后移一位。

反复进行上面的操作,直到i>j时停止操作。

while(i<j){
    if(a[i]+a[j]==m){
        printf("%d %d\n",i,j);
        i++;j++;
}else if(a[i]+a[j]<m){
        i++;
}else j--;
}

如此便会将所有的答案进行输出。

运用此思想还可以将两个有序的数列进行合并,我们只需从两个数列第一个元素进行比较,如果小,就加入第三个数列,然后往后移一位,意思就是谁小谁进第三个数列,结束后,第三个数列就是合并后的有序数列。

最后总结一下吧,递归思想在程序设计里是一个很重要的算法思想,在后面的深度搜索里用的就是递归思想,比如上面呢个n皇后的题目。还有下面的two pointers思想,是一个很巧的思想,如果当时考试的时候我会的话,也不至于呢么狼狈,哈哈哈哈哈。因此我们就要多见,见得多了脑子里的东西也就多了,思路也会变得更加地灵活。将我们继续学习吧。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值