ACM学习<二>

穷举算法思想:

    一句话:就是从所有可能的情况,搜索出正确的答案。

步骤:

    1.对于一种可能的情况,计算其结果。

    2.判断结果是否满足,YES计算下一个,no继续步骤1,然后判断下个可能的情况。

实例:

    孙子算经--鸡兔同笼:头35,脚94,几鸡几兔?

    

    

#include <iostream>                                                       //头文件
using namespace std;
int qiongju(int head, int foot , int *chicken,int *rabbit)     //穷举算法
{
     int re,i,j;
     re=0;
     for(i=0;i<=head;i++)                                             //循环
     {
          j=head-i;
          if(i*2+j*4==foot)                                             //判断,找到答案
          {
               re=1;
               *chicken=i;
               *rabbit=j;
          }
     }
     return re;
}
int main()                                                                 //主函数
{
     int chicken,rabbit,head,foot;
     int re;
     cout<<"鸡兔同笼问题:"<<endl;
     cout<<"输入头数:";
     cin >>head;
     cout<<"输入脚数:";
     cin >>foot;
     re =qiongju(head,foot,&chicken,&rabbit);                    //& 跟 qiongju()里面的 * 是不是表示  引用??
     if(re==1)
     {
          cout<<"鸡有:"<<chicken<<"只, 兔有"<<rabbit<<"只。" <<endl;
     }else
     {
          cout<<"无法求解!"<<endl;
     }
}

 

 

递推思想:

     1.根据已知的结果和关系,求解中间的结果。

     2.判断是否达到要求,如果没有达到,则继续根据已知的结果和关系求解中间结果。如果有的话,则表示寻找到一个正确的结果。

 实例:斐波那契数列———兔子产子

#include <iostream>
using namespace std;
int fibonacci(int n)
{
     if(n==1 || n==2)
     {
          return 1;
     }
     else
     {
          return fibonacci(n-1)+fibonacci(n-2);//递归调用
     }
}
int main()
{
     int n,num;
     cout<<"斐波那契数列——兔子产子:"<<endl;
     cout<<"请输入时间:";
     cin >> n;
     num=fibonacci(n);
     cout<<"经过"<<n<<"年,可以产子"<<num<<"对"<<endl;
}

 

 

递归思想:

     递归算法,就是在程序中不断反复调用他自身的函数调用方式,这种函数也称为递归函数。

                     函数的递归调用用分两种情况:直接递归和间接递归。

                     直接递归:即在函数中调用函数本身。

                     间接递归:即间接地调用一个函数,如func_a调用了func_b,func_b又调用了func_a;间接递归用的不多。

     优点:代码间接清晰,可读性更好。用递归比循环表死简洁精炼。特别人工智能,八皇后问题,汉诺塔等适合用递归

     缺点:没有明显的减少代码规模和节省内存空间。 递归比非递归运行速度要慢一些。附加函数增加了时间的开销(要执行一系列的压栈出栈)。二者递归层次太深还可能导致堆栈溢出。

     实例:经典的阶乘

#include <iostream>
using namespace std;
long fact(int n); //函数的声明
int main()
{
     int i;
     cout<<"请输入要求阶乘的一个整数:";
     cin >>i;
     cout<<i<<"的阶乘结果为"<<fact(i)<<endl;
}
long fact(int n)
{
     if(n<=1)
          return 1;
     else
          return n*fact(n-1);
}

分治算法思想:

     基本思路:将一个计算复杂的问题分为规模较小,计算简单的小问题求解,然后综合各个小问题,得到最终问题的答案。

     基本过程:

     1.对于一个规模为N的问题若该问题可以容易的解决,那就直接解决。否则执行下面的步骤。

     2.将该问题分解为M个规模较小的子问题,这些子问题五项多里,并且与原问题形式相同。

     3.递归的解子问题。

     4.然后,将各子问题的解合并得到原问题的解。

例子:

    问题:一个袋子30个硬币,一个假的,假的较轻。如何分辨假币?

    步骤:

          1.首先为每个币编号,分成两份,放在天平上。

          2.因为假币在轻的一方,继续将轻的重复上面的做法。

          3.直到剩下2个,直接用天平找出。

#include <iostream>
using namespace std;
#define MAXNUM 4
int FalseCoin(int coin[],int low,int high)
{
     int i,sum1,sum2,sum3;
     int re;
     sum1=sum2=sum3=0;
     if(low+1==high)//最后一堆是两个的时候
     {
          if(coin[low]<coin[high])
          {
               re=low+1;
               return re;
          }
          else
          {
               re=high+1;
               return re;
          }
     }
     if((high-low+1)%2==0)//n为偶数
     {
          for(i=low;i<=low+(high-low)/2;i++)
          {
               sum1+=coin[i];//前半段和
          }
          for(i=low+(high-low)/2+1;i<=high;i++)
          {
               sum2+=coin[i];//后半段和
          }
          if(sum1>sum2)
          {
               re=FalseCoin(coin,low+(high-low)/2+1,high);
               return re;
          }
          else if(sum1<sum2)
          {
               re=FalseCoin(coin,low,low+(high-low)/2);
               return re;
          }
          else
          {

          }
     }
     else    //n为奇数
     {
          for(i=low;i<=low+(high-low)/2-1;i++)
          {
               sum1+=coin[i];//前半段和
          }
          for(i=low+(high-low)/2+1;i<=high;i++)
          {
               sum2+=coin[i];//后半段和
          }
          sum3=coin[low+(high-low)/2];
          if(sum1>sum2)
          {
               re=FalseCoin(coin,low+(high-low)/2+1,high);
               return re;
          }
          else if(sum1<sum2)
          {
               re=FalseCoin(coin,low,low+(high-low)/2-1);
               return re;
          }
          else
          {

          }
          if(sum1+sum3==sum2+sum3)
          {
               re=low+(high-low)/2+1;
               return re;
          }
     }
}
int main()
{
      int coin[MAXNUM];
       int i,n;
       int place;
       cout<<"分治法求假币问题!"<<endl;
       cout<<"请输入币的个数:";
      cin >>n;
      cout<<"请输入币真假的重量:";
      for(i=0;i<n;i++)
      {
          cin >> coin[i];
           //scanf("%d",&coin[i]);
      }
      place =FalseCoin(coin,0,n-1);
      cout<<"位子实在上述的第"<<place<<"个是假的"<<endl;
}

 

概率算法思想:

     1.将问题转化为相应的几何图形S,S的面积是容易计算的。问题往往是对应的集合图形的S1的面积,

     2.然后向几何随机撒点。

     3.统计S S1的点数,根据关系得出结果。

     4.判断是否达到精度,否执行2步骤,是 结束

          4种形式:数值概率算法,蒙特卡罗算法 ,拉斯维加斯算法,舍伍德算法。

    蒙特卡罗概率算法 计算PI:

#include <iostream>
#include <time.h>
using namespace std;
double MontePI(int n)
{
     double PI;
     double x,y;
     int i , sum;
     sum = 0;
     srand(time(NULL));
     for(i=1;i<n;i++)
     {
          x=(double)rand()/RAND_MAX;
          y=(double)rand()/RAND_MAX;
          if(x*x+y*y<=1)
               sum++;
     }
     PI=4.0*sum/n;
     return PI;
}
int main()
{
     int n;
     double PI;
     cout<<"蒙特卡罗概率算法 计算PI"<<endl;
     cout<<"输入撒点的数量:";
     cin >> n;
     PI=MontePI(n);
     cout<<PI<<endl;
}
时间: 2024-08-06 06:09:46

ACM学习<二>的相关文章

ACM学习&lt;一&gt;

c++指针|指针入门   什么是指针? 其实指针就像是其它变量一样,所不同的是一般的变量包含的是实际的真实的数据,而指针是一个指示器,它告诉程序在内存的哪块区域可以找到数据.这是一个非常重要的概念,有很多程序和算法都是围绕指针而设计的,如链表. 开始学习 如何定义一个指针呢?就像你定义一个其它变量一样,只不过你要在指针名字前加上一个星号.我们来看一个例子: 下面这个程序定义了两个指针,它们都是指向整型数据. int* pNumberOne; int* pNumberTwo; 你注意到在两个变量名

ACM学习&lt;3&gt;

  排序算法:            基本:冒泡,快速,选择,堆,插入,shell      多路并归: 1.冒泡排序:      思想:交换排序,通过相邻的交换来达到排序的目的.      流程:           1.对数组中的各数据,依次比较相邻两个元素的大小.           2.如果前面的大,交换.经过一轮,可把最小的排好.           3.然后用同样的方法,把剩下的数据排好.最后从小到大排好相应的数据. #include <iostream> #include <

写给大二想投入ACM的女生

[来信] 您好!我是学计算机的一名大二女生,大一基础学得不好,不注重专业学习,也不知道自己到底喜不喜欢这个专业,浑浑噩噩的就过去一年了,大二想补回来,说不清楚喜不喜欢,适不适合当程序员,但我觉得还是要好好学好专业知识,提高编程能力,在对它有更多的了解之后再判定这些纠结的问题. 最近加入了我们学院的ACM实验室,开始刷acm的基础题目,也想开始发表csdn博客,见证专业学习成长,分享经验心得,您对我在acm学习等方面有建议吗?您认为一个基础差的女生有必要对ACM投入时间吗?大二是很关键的一年,我自

ACM协会编程学习座谈的记录和思考

ACM协会的负责同学和我说,大一的同学不少说编程难学,想让我做个讲座.我说,让我讲多没意思,不如搞个座谈,让感觉困难的同学说说究竟是什么困难,有针对性地,老师.高年级同学,以及同年级克服了这些困难的同学,说说对策,相互启发.当然,我可以参加. 于是有了11月28日晚,在大活206的座谈.我还找了课程组负责人周老师,她也感兴趣去听听同学们的困难,一起想想办法.我通知了几个我带的班上学习已经进入轨道的同学(特意地安排有女生)去,好给大家传达点学习经验. 谁知,座谈的参加人员,十来个负责协会工作的大二

ACM算法数论学习

                               

CCAI 2017 | 邓小铁:金融博弈下的价值学习

在大会的智能金融论坛上,邓小铁教授发表了题为<金融博弈下的价值学习>的分享. 邓小铁现任上海交通大学计算机系致远讲席教授,曾获得清华大学工学学士学位.中国科学院硕士学位以及斯坦福大学博士,曾在英国利物浦大学.香港城市大学和加拿大约克大学任教. 在此之前, 他是西门弗雷泽大学的加拿大自然科学与工程技术研究理事会国际博士后研究员.因为对算法和博弈理论交互研究的贡献,于2008年获选ACM会士.2013年入选国家千人计划. 目前的重点研究算法博弈理论包括均衡分析和机制设计, 并应用于互联网经济学金融

细说循序渐进学习Ajax的途径

ajax 现在浏览器端以 JavaScript 为核心,基于各种 Web 标准(即:早已完成标准化的XHTML/CSS/DOM/XML/XSLT 和正在进行标准化的XMLHTTP)的技术正在加速整合,Ajax 就是这一系列技术的一个统称. 虽然网络上已经有大量的相关资源,但是为了打好基础,认真读上几本书还是很有必要的.好在 Ajax 并不是什么全新的技术,它仅仅是传统技术的发展和增值,是对于这些基于 Web 标准的传统技术的重新包装,使其更加适合于企业应用,并且和服务器端结合地更加紧密.因此学习

如何循序渐进学习Ajax教程?

ajax|教程 现在浏览器端以 JavaScript 为核心,基于各种 Web 标准(即:早已完成标准化的XHTML/CSS/DOM/XML/XSLT 和正在进行标准化的XMLHTTP)的技术正在加速整合,Ajax 就是这一系列技术的一个统称. 虽然网络上已经有大量的相关资源,但是为了打好基础,认真读上几本书还是很有必要的.好在 Ajax 并不是什么全新的技术,它仅仅是传统技术的发展和增值,是对于这些基于 Web 标准的传统技术的重新包装,使其更加适合于企业应用,并且和服务器端结合地更加紧密.因

循序渐进学习Ajax的途径

ajax 现在浏览器端以 JavaScript 为核心,基于各种 Web 标准(即:早已完成标准化的 XHTML/CSS/DOM/XML/XSLT 和正在进行标准化的 XMLHttpRequest)的技术正在加速整合,Ajax 就是这一系列技术的一个统称.  虽然网络上已经有大量的相关资源,但是为了打好基础,认真读上几本书还是很有必要的.好在 Ajax 并不是什么全新的技术,它仅仅是传统技术的发展和增值,是对于这些基于 Web 标准的传统技术的重新包装,使其更加适合于企业应用,并且和服务器端结合