C++知识点总结

一、信奥入门须知

1.iostream标准输入输出。

2.每次都必须要打的7行代码。

#include <iostream>

using namespace std;

int main(){

    return 0;

}

3.变量的命名规则是字母,数字,下划线组合,但字母不能在首位。

4.//表示注释,/*……*/表示多行注释。

5.int a,b,c为变量命名。

6.数据类型:int整数,float 单精度浮点型,double双精度浮点型(float,double 显示均为小数,其中双精度浮点型范围更大)

7.cout<<a<<endl;表示换行。

8.int x;

cin >>x;

cout <<x;(输入一个数再输出这个数)

  • 运算
  1. 自加自减符:i++,i—(或++i,—i)注:++,—仅能+1,-1
  2. 复合算数运算符:+=,-=,*=,/=
  3. 关系运算符:>,<,==,!=(不等于),>=,<=
  4. 逻辑运算符:&&(and),//(or),!(非)
  5. 1代表正确,0代表错误
  6. /除,%取余,//求余,=赋值
  7. 四则运算模版题

float a,b,c;

cin>>a;

cin>>b;

c=a+b;

cout<<c;

  1. 典型例题:地球人口问题

cin>>x>>a>>y>>b;

v=(b*y-a*x)/(b-a);

  1. 自加自减

int i=2;

i -=1;(或*,/,+)

cout <<i.

  1. 关系运算符

int a=5,b=5,c,d;

c=a==b;

cout<<c;

  1. 逻辑运算符

int a=5,b=5,c=1,d=1;

int x,y;

x=(a!=b)&&( c==d)

cout<<x;

12.0&&1==0,0//1==1,0&&0==0,0//0==0,1&&0==0,1//0==1,1&&1==1,1//1==1

  1. int的范围为max=2^31
  2. char字符型
  3. 字符型赋值加‘ ’

char c=‘A’;

cout<<c;

  1. 另一种输入输出:

scanf (“%c”,&c);

printf(“%c”,c);

  1. int 整形%d;float %f,double,%lf,char,%c
  2. 兀符号常量 const double pi=3.14159
  • 选择语句
  1. if单分支结构选择语句

if(a==b){

printf (“A\n”);

}

  1. if…else …双分支结构选择语句

if(a==b){

printf (“A\n”);

}else {

printf (“B\n”);

}

  1. 三分支结构选择语句

   if…else if…else…

  1. %无法用在double中
  2. ? 三元运算符
  3. 双分支三元运算符

a=b>6?c=d;

  1. switch 多分支结构选择语句

switch (n){

case 1:printf (“5”);break;

case 2:printf (“6”);break;

case 3:printf (“7”);break;

case 4:printf (“8”);break;

}

  • 循环语句
  1. for 循环

for(控制变量初始化表达式;条件表达式;增量表达式){

循环体语句

}

  1. 非0即真,0即假
  2. while 循环. while (条件表达式){语句}
  3. do—while 语句

循环控制变量的初始化

do{

增量表达式;

}while (条件表达式)

  1. 循环嵌套 (for循环不断累加)
  2. continue 是指跳回for循环的开始,执行调整语句,执行调整语句并判断循环条件,就是直接进行下一次循环;break 是指直接跳出循环.
  • 数组
  1. 一维数组的定义:当数组中,每个元素只带有一个下标时,我们称这样的数组为一维数组
  2. 一维数组的定义格式:类型标识符  数祖名[常量表达式]

      注:常量表达式表示数组元素个数,可以是常量和符号常量,但不能是变量(如int a[10];a[10]不属于该数组的空间范围,该数组的空间范围为0到9)

  1. 下标可以是任意值为整形的表达式,该表达式里可以包含变量和函数调用,引用时,下标值应在数组定义的下标值范围内
  2. 一维数组的初始化:数字的初始化可以在定义时一并完成。

类型标识符 数组名[常量表达式]={值1,值2…}

  1. 在初值列表中可以写出全部数组元素的值,也可以写出部分
  2. 对数组元素全部初始化为0,可以简写为:{}
  1. 数组越界

(1)数组元素的下标值为非负整数;

(2)在定义元素的个数的下标范围内使用;

定义:当在程序中把下标写成负数、大于数组元素的个数时,程序编译的时候是不会出错的,这些语句的语法是正确的,能够通过程序的编译,然而,他们要访问的数组元素,并不在数组的存储空间中,这种现象叫数组的越界。

  1. 使用函数memcpy 要包含头文件cstring
  2. 当一维数组元素的类型也是一维数组时,便构成了“数组的数组”,即二维数组
  3. 二维数组的定义格式:数据类型 数组名[常量表达式1][常量表达式2];
  4. 当定义的数组下标有多个时,我们称为多维数组,下标的个数并不局限在一个或两个,可以任意多个
  5. 二维数组元素的引用:二维数组的数组元素的引用与一维数组元素引用类似,区别在于二维数组元素的引用必须给出两个下标。

引用格式为:<数组名>[下标1][下标2]

  1. 二维数组的初始化和一维数组类似。可以将每一行分开来写在各自的括号里,也可以把所有数据写在一个括号里。
  • 字符类型和字符数组
  1. 字符类型为由一个字符组成的字符常量或字符变量
  2. 字符常量定义:

const 字符常量=‘字符’

字符变量定义

char 字符变量

字符类型是一个有序类型,字符的大小顺序按其ASC II的大小而定

3.1KB=1024(2^10)Byte 1MB=1024KB 1GB=1024MB 1TB=1024GB

1PB=1024TB 1EB=1024PB  1字节=8B

  1. int=4字节=32Btye(第一格为符号,范围为0~2^31-1) int(-2^31~2^31-1)

long long=8字节=64bit (名字为超长整形,-2^63~2^63-1)

  1. ASC II表 ‘0’~’9’=48~57; ‘A’~’Z’=65~90;’a’~’z’=97~122
  2. 字符数组是指元素为字符的数组.字符数组是用来存放字符序列或字符串的.字符数组也有一维、二维和三维之分。
  3. 字符数组的定义格式

字符数组定义格式同于一般数组,所不同的是数组类型是字符型,第一个元素同样是从chl [0]开始,而不是chl[1]:[存储类型]char数组名[常量表达式1]

  1. 字符数组的赋值

字符数组赋指类似于一维数,赋值分为数组的初始化和数组元素的赋值。初始化的方式有用字符初始化和用字符串初始化两种,也有用初始值表进行初始化的

  1. 字符串的输入和输出:1.输入:从键盘输入一个字符数组,可以使用scanf 语句和gets 语句
  1. scanf 语句

格式:scanf(“%s”,字符串名称),

注:这里的字符串名称之前不加&这个取地址符.

       系统会自动在输入的字符串常量后添加’/0’标志,因此在输入时仅输入字符串的内容

       输入多个字符串时,以空格分隔

  1. gets 语句

格式:gets(字符串名称);使用gets只能输入一个字符串

  1. 输出:向屏幕输出一个字符串,可以使用prinf语句或puts语句
  1. printf 语句

格式:printf(“%s”,字符串名称);

  1. puts语句

格式:puts(字符串名称);

  • 函数
  1. 函数定义的语法形式

数据类型 函数名(形式参数表){

函数体

}

  1. 函数的形式:函数的形式从结构上说,可以分为三种无参函数,有参函数和空函数。
  1. 无参函数

无参函数顾名思义即为没有参数传递的函数,无参函数一般不需要带回函数值,所以函数类型说明为void

  1. 有参函数

有参函数即为有参数传递的函数,一般是要带回函数值

  1. 空函数

空函数即函数体只有一对花括号,花括号内没有任何语句的函数,空函数不完成什么工作,只占据一个位置,在大型程序设计中,空函数用于扩充函数功能

  1. 函数的声明和调用:1.函数的声明:调用函数之前,先要声明函数原型,在主调函数中或 所有函数定义之前按如下形式声明:

类型说明符 被调函数名(含类型说明的形参表)

  1. 函数的调用:声明了函数原形之后,便可以按如下形式调用 函数:

函数名(实参列表)

  1. 函数的返回值

在组成函数体的各类语句中,值得注意的是返回语句return.它的一般格式是:

return(表达式);

  1. 常见函数
  1. 判断是否为质数

void get_prime (int p){

for(int i=2;i*i<=p;i++){

if(p%i==0){

retrun 0;

}

}

return 1;

}

  1. 判断是否为回文数

bool hw(int x){

int m[10]={};

while(x>0){

m[++a]=x%10;

x/=10;}

for(int i=1;i<=a/2;i++){

if(m[i]!=m[a-i+1]){

return 0;

}

}retrun 1;

}

  1. 全局变量、局部变量及它们的作用域

在函数,外部定义的变量称为外部变量或全局变量在函数内部定义的变量称为内部变量或局部变量

  1. 全局变量:第一在函数起来的变量称为全局变量,全局变量的作用域是从变量定义的位置开始到文件结束.由于全局变量是在函数外部定义的,因此对所有函数而言,都是外部的,可以在文件中位于全局变量定义后面的任何函数中使用.
  2. 局部变量:局部变量的作用域是在定义该变量的函数内部。换句话说,局部变量只在定义它的函数内有效,函数的形参也是局部变量,局部变量存储空间是临时分配的,当函数执行完毕,局部变量的空间就被释放,其中的值无法保留到下次使用。
  • 递归算法
  1. 定义:当函数定义中,其内部操作又直接或间接地出现对自身的调用,则称这样的程序嵌套定义为递归定义。
  2. 特点:递归通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量程序就可描述出解题过程所需要的多次重复计算,大大减少了程序的代码量,递归的能力在于用有限的语句来定义对象的无限集合,用递归思想写出程序往往十分简洁易懂
  3. 使用:
  1. 简单地说递归算法的本质就是自己调用自己,用调用自己的方法去处理问题,可使解决问题变的简洁明了。
  2. 模式:

①将调用程序的返回地址,相应的调用前的变量都保存在系统堆栈中

②执行被调用的函数

③若满足退出递归的条件,则退出递归并从栈顶上弹回返回地址,取回保存起来的变量值,继续沿着返回地址,向下执行程序

④否则继续递归调用,只是地递归的参数发生变化,增加一个量或减少一个量,重复执行,直到递归调用结束

  1. 算法要求
  1. 要求求解的问题可以化为子问题求解,其子问题的求解方法与原问题相同,只是规模上增加或减少
  2. 递归调用的次数是有限的,必须有递归结束的条件(称为递归边界)
  • 文件和结构体
  1. 文件:文件是根据特定的目的而收集在一起的有关数据的集合,分为文本文件和二进制文件
  2. 文件操作步骤:
  1. 打开文件,将文件指针指向文件,决定打开文件类型
  2. 对文件进行读、写操作
  3. 在使用完文件后,关闭文件
  1. 定义结构体及结构体变量:结构体变量的定义有两种形式
  1. 第一结构体类型的同时定义变量

struct 结构体类型名{

成员表;

成员函数;

}结构体变量表;

  1. 先定义结构体再定义结构体变量

struct 结构体类型名{

成员表;

成员函数;

};

结构体名 结构体变量表

注:在定义结构体变量时注意,结构体变量名和结构体名不能相同.在定义结构体时,系统对其不分配实际内存,只有定义结构体变量时,系统才为其分配内存

  1. 结构体变量的特点
  1. 结构体变量可以整体操作
  2. 结构体变量的成员访问也很方便、清晰
  3. 结构体变量的初始化和数组的初始化类似
  1. 成员调用:结构体变量与各个成员之间引用的一般形式为

结构体变量名.成员名(成员运算符”.”在存储成员数值时使用,其优先级最高,并具有左结合性.)

  1. 成员函数调用:成员函数调用的一般形式为:

结构体变量名.成员名

  • 高精度计算
  1. 数据的接收和存贮:当输入的数很长时,可采用字符串方式输入,这样可输入位数很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组中,另一种方法是直接用循环加数组方法输入数据
  2. 高经度数位数的确定:接收时往往使用字符串的,所以它的位数就等于字符串长度
  3. 进位、借位处理

加法进位:c[i]=a[i]+b[i];

减法借位:c[i]=a[i]-b[i];

乘法进位:c[i+j-1]%=10;

商和余数的求法:视被除数和除数的位数情况进行处理

  • 排序
  1. 冒泡排序的步骤:
  1. 读入数据存放在a数组中
  2. 比较相邻的前后两个数据,如果前面数据大于后面的数据就将两个数据交换.
  3. 对数组的第1个数据到第n个数据继续进行一次遍历后,最大的一个数据就“冒”到数组前n个位置
  4. n=n-1,如果n不唯一就重复前面二步,否则排序完成
  5. 程序实现方法:用两层循环完成算法,外层循环i控制每轮要进行多少次的比较,第一轮比较n-1次,第二轮比较n-2次,……最后一轮比较1次.内存循环j控制每轮i次比较相邻,两个元素是否逆序,若逆序就交换这两个元素
  1. 归并排序

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用,将已有序的子序列合并,得到完全有序的序列,即先使每个子序列有序,再使子序列段间有序,若两个有序表合并成一个有序表,称为二路归并

归并排序是稳定的排序,即相等的元素的顺序不会改变,而且速度快

代码:#include<bits/stdc++.h>

using namespace std;

const int N=100050;

int n,p[N],temp[N];

long long merge_sort(int left,int right){

if(left>=right){

return 0;

}

int mid=(left+right)/2;

long long res=0;

res=merge_sort(left,mid)+merge_sort(mid+1,right);

int i=left,j=mid+1,k=0;

while(i<=mid&&j<=right){

if(p[i]<=p[j]) temp[k++]=p[i++];

else{

temp[k++]=p[j++];

res+=mid-i+1;

}

}

while(i<=mid) temp[k++]=p[i++];

while(j<=right) temp[k++]=p[j++];

for(int i=left,j=0;i<=right;i++,j++){

p[i]=temp[j];

}

return res;

}

int main(){

cin>>n;

for(int i=0;i<n;i++) cin>>p[i];

cout<<merge_sort(0,n-1);

return 0;

}

  1. 快速排序:是最简单的排序方法,速度很快,但它是不稳定的排序方法

代码:#include<bits/stdc++.h>

using namespace std;

int n,p[100050];

bool cmp(int a,int b){

return a<b;

}

int main(){

cin>>n;

for(int i=0;i<n;i++) cin>>p[i];

sort(p,p+n,cmp);

for(int i=0;i<n;i++) cout<<p[i]<<" ";

return 0;

}

  • 递推算法
  1. 定义:递推法是一种重要的数学方法,在数学的各个领域中都有广泛的运用,也是计算机用于数值计算的一个重要算法.
  2. 特点:一个问题的求解需一系列的计算,在已知条件和所求问题之间总存在着某种相互联系的关系,在计算时,如果可以找到前后过程之间的数量关系(即递推式),那么,从问题出发逐步推到已知条件,这种方法叫逆推,无论顺推还是逆推,其关键是要找到递推式,这种处理问题的方法能使复杂运算化为若干部重复的简单运算,充分发挥出计算机擅长于重复计算重复处理的特点
  3. 典型的递推关系
  1. 汉诺塔问题

 int n = 10;//n表示有几个盘片

        //开辟一块空间,这里用n+1个空间,索引为0的没用到,索引为i表示dp存储i片盘的移动次数

        int[] dp = new int[n + 1];

        dp[1] = 1;//设初值

        //i小于n的解全部算出来,最终得到n的解

        for (int i = 2; i <= n; i++;) { //设2为开始求解的问题

            dp[i] = 2 * dp[i - 1] + 1;//递推公式

        }

        //输出结果

        for (int index = 1; index < dp.length; index++) {

            System.out.println(index + "片盘移动的次数为:" + dp[index]);

        }

    }

}

  1. 过河卒问题

#include<bits/stdc++.h>

int main()

{

    int i,j,x,y,n,m,forb[51][51];

    long long  ans[51][51];

    int dx[8]={-2,-1,1,2,2,1,-1,-2};

    int dy[8]={1,2,2,1,-1,-2,-2,-1};

    scanf("%d %d %d %d",&n,&m,&x,&y);

    for (i=0;i<=n;i++)

        for (j=0;j<=m;j++)

        {

            forb[i][j]=0;

            ans[i][j]=0;

        }

    ans[0][0]=1;

    forb[x][y]=1;

    for (i=0;i<8; i++)

            if (x+dx[i]>=0 && x+dx[i]<=n && y+dy[i]>=0 && y+dy[i]<=m)

                   forb[x+dx[i]][y+dy[i]]=1;

   for (i=1; i<=n; i++)

        if (forb[i][0]==0)

            ans[i][0]=1;

        else break;

  for (i=1; i<=m; i++)

        if (forb[0][i]==0)

            ans[0][i]=1;

        else break;

   for (i=1; i<=n; i++)

        for (j=1; j<=m; j++)

            if (forb[i][j]==0)

                ans[i][j]=ans[i-1][j]+ans[i][j-1];

    printf("%ld\n",ans[n][m]);

    return 0;

}

  • 搜索与回溯算法
  1. 回溯是多搜索算法中的一种控制策略,它的基本思想是为了求得问题的解。先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回一步,重新选择继续向前搜索如此反复进行,直到得到解或证明无解。
  2. 代码框架
  1. 素数环

#include<bits/stdc++.h>

using namespace std;

int a[25];

int n,m;

bool pri[50],b[25];

bool prime(int p){

for(int i=2;i<=sqrt(p);i++){

if(p%i==0){

return 0;

}

}return 1;

}

void output(){

cout<<a[1];

for(int i=2;i<=n;i++){

cout<<" "<<a[i];

}

cout<<"\n";

}

void vc(int x){

if(m>=10) return;

if(x>n){

if(pri[a[n]+1]){

output();

m++;

}

return;

}

for(int i=2;i<=n;i++){

if(!b[i]&&pri[a[x-1]+i]){

a[x]=i;

b[i]=1;

vc(x+1);

b[i]=0;

}

}

}

  

int main(){

for(int i=2;i<50;i++){

if(prime(i)) pri[i]=1;

}

cin>>n;

if(n%2==1) return 0;

a[1]=1,b[1]=1;

vc(2);

return 0;

}

  1. 八皇后

#include<bits/stdc++.h>

using namespace std;

bool a[20],b[20],c[20];

int n,m,o[20],v;

void output(){

for(int i=1;i<=n;i++){

cout<<o[i]<<" ";

}

cout<<"\n";

}

void vc(int x){

if(x>n){

if(m<3){

output();

m++;

}

v++;

return;

}

for(int i=1;i<=n;i++){

if(a[i]==0&&b[x+i]==0&&c[x-i+n]==0){

o[x]=i;

a[i]=1,b[x+i]=1,c[x-i+n]=1;

vc(x+1);

a[i]=0,b[x+i]=0,c[x-i+n]=0;

}

}

}

  

int main(){

cin>>n;

vc(1);

cout<<v;

return 0;

}

  • 贪心算法
  1. 所谓贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。
  2. 贪心算法没有固定的算法框架,算法设计的核心是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择贪心策略必须具备无后效性即某个状态以后的过程不会影响以前状态,只与当前状态有关。所以对所采用的贪心策略,一定要仔细分析其是否满足无后效性。
  3. 基本思路:
  1. 建立数学模型来描述问题
  2. 把求解的问题分成若干个子问题
  3. 对每一子问题求解,得到此问题的局部最优解
  4. 把子问题的解局部最优解合成原来解问题的一个解

4.实现框架

从问题的某一初始解出发;

while (能朝给定总目标前进一步){

利用可行的决策,求出可行解的一个解元素;

}

有所有解元素组合成问题的一个可行解;

  1. 要用自己脑袋思考,写代码之前要先分析问题,在草稿纸上演算,再写代码
  2. 典型例题
  1. 排队打水问题

#include <bits/stdc++.h>

using namespace std;

long long sum=0;

int n,a[100050];

int main(){

cin>>n;

for(int i=1;i<=n;i++){

cin>>a[i];

}

sort(a+1,a+n+1);

for(int i=1;i<n;i++){

sum+=(n-i)*a[i];

}

    cout<<sum;

    return 0;

}

  1. 排队接水问题(多个水龙头)

#include<iostream>

#include<algorithm>

using namespace std;

const int N = 1005;

int a[N],b[N];

int main(){

int n,r,sum=0;

cin>>n>>r;

for (int i=1; i<=n; i++) cin>>a[i];

sort(a+1,a+n+1);

for (int i=1; i<=r; i++) b[i]=a[i];

for (int i=r+1; i<=n; i++) b[i]=b[i-r]+a[i];

for (int i=1; i<=n; i++) sum+=b[i];

cout<<sum<<endl;

return 0;

}

  • 动态规划
  1. 动态规划程序设计是对解最优化问题的一种途径、一种方法,而不是一种特殊算法,不像前面所述的那些搜索或数值计算,具有一个标准的数学表达式和清晰明确的解题方法动态规划程序设计往往是针对一种最优化问题,由于各种问题的性质不同,确定最优解的条件也互不相同,因而动态规划的设计方法对不同的问题,有各具特色的解题方法,而不存在一种万能的动态规划算法,可以解决各类最优化问题。
  2. 典型例题背包问题

(1)01背包问题

#include <bits/stdc++.h>

using namespace std;

const int N =40;

const int M=250;

struct node{

int w,c;

}q[N];

int n,m,ans,dp[N][M];

int main(){

cin>>m>>n;

for(int i=1;i<=n;i++) {

cin>>q[i].w>>q[i].c;

for(int j=1;j<=m;j++)

if (j<q[i].w) dp[i][j]=dp[i-1][j];

else dp[i][j] = max(dp[i][j],dp[i-1][j-q[i].w]+q[i].c);

}

cout<<dp[n][m];

return 0;

}

  1. 完全背包问题

#include <bits/stdc++.h>

using namespace std;

const int N=110;

struct node{

int v,w,s;

}q[N];

int n,m,dp[N][N];

int main(){

cin>>n>>m;

for(int i=1;i<=n;i++) {

cin>>q[i].v>>q[i].w>>q[i].s;

}

for(int i=1;i<=n;i++){

for(int j=1;j<=m;j++){

for(int k=0;k<=q[i].s&&k*q[i].v<=j;k++){

 dp[i][j] = max(dp[i][j],dp[i-1][j-k*q[i].v]+k*q[i].w);

}

}

}

cout<<dp[n][m];

return 0;

}

Dfs(一)深度优先搜索(DFS)

1.深度优先搜索的定义

简单地说,图的深度优先搜索可概括为尽可能深地去搜索一个图,是一个递归的过程(需要用到栈存储),通过遍历邻接表或邻接矩阵的方式深入搜索一个图,直到访问完所有连通的顶点,若当前分支已经访问过,则会回溯到上一个顶点,继续搜索其他分支顶点,直到所有顶点被访问。

递归这一点就类似树的先序遍历,先访问结点,然后递归向外层结点遍历,尽可能深地搜索一个图,都采用回溯算法。

图的深度优先搜索首先选取图中某一顶点vi,访问后,任意选取一个与vi邻接的顶点,且该顶点未被访问,……,继续重复该过程,直到图中所有与vi连通的顶点都被访问到;若还有顶点未被访问到,则另外选取一个未被访问的顶点再次作为起始点,重复以上步骤,继续直至图中所有结点被访问。

                        

原文链接:数据结构与算法设计分析——常用搜索算法-CSDN博客

2.操作步骤

一.初始原点为v0,使用深度优先搜索,首先访问 v0 -> v1 -> v2 -> v5,到 v5 后面没有结点,则回溯到 v1 ,即最近的且连接有没访问结点的结点v1;

二.此次从 v1 出发,访问 v1 -> v4 -> v6 -> v3,此时与v3相连的两个结点 v0 与 v6 都已经访问过,回溯到 v6 (v6 具有没访问过的结点);

三.此次从 v6 出发,访问 v6 -> v7,到 v7 后面没有结点,回溯;

四.一直回溯到源点 v0 ,没有没访问过的结点,程序结束。                      

3.模板代码

1.典例题目

*素数环

一个环由n个圈组成,将自然数1-n放入圈内,使得任意相邻圈的两个数之和均为素数。第一个圈的元素均为1。下图为n=6时的一个例子:

           

#include<bits/stdc++.h>

Using nmaespace std;

int n;

int a[100]= {0};

int b[100]= {0};

void huan(int t) {

int i;

if(t==n&&su(a[n-1]+a[0])) { //终止条件有两个,一个是首尾相接是否是素数,一个是圈内元素的个数,需要达到n(由用户输入)

for(i=0; i<n; i++) { //输出结果(但是每一次的输出都只是一个满足条件的“树枝”,不满足条件的会被筛掉)

printf("%d ",a[i]);             //如果该if条件成立,则该“树枝”到头了

}

printf("\n");

} else {

for(i=2; i<=n; i++) {

if(b[i-1]==0) {              //是否被使用

a[t]=i;                  //给数组a赋值

b[i-1]=1;                //已经使用,在递归

if(su(a[t]+a[t-1])) {     //回溯操作(这需要满足条件(为素数))

huan(t+1);

}

b[i-1]=0;                 //递归完,在给第二次循环使用,确保数据不变

}

}

}

}

int su(int m) {                  //该函数用于判断是否是素数,是huan函数的一个判断条件,对应模板中的终止条件

int i;

if(m<3) return 0;

else {

for(i=2; i<=sqrt(m); i++) {

if(m%i==0) {

return 0;

break;

}

}

}

return 1;

}

int main() {

scanf("%d",&n);

a[0]=1;          //初始化变量

b[0]=1;

huan(1);          //从1开始遍列

return 0;

}

*迷宫

题目链接:迷宫 - 洛谷

每天只打一点点

主要为整理与总结(借鉴了一下dalao的文章)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值