目录

蛮力法(brute force):

【例4-1】链环数字对

 问题分析

 计算模型

pair_digital(int n):

代码:

【例4-2】解数字迷:

思考题:ACM预测:​

问题分析:

计算模型:

算法分析:

Assume():

代码

【例4-3】输出玫瑰矩阵,其为n*n的方阵,特征如下所示:

思考题:

算法2:

算法分析:

代码:

问题分析:

计算模型:

二、穷举查找

【例4-4】旅行商问题(traveling salesman problem,TSP)——排列树

问题分析

计算模型

代码:

1.蛮力字符比较

2.旅行路线 效率类型

3.城市个数

【例4-5】背包问题。——组合森林

 问题分析

 计算模型

图的搜索

思考题

1.广度优先 三壶问题

2.广度优先 迷宫最优解

代码00:队列

01:栈

02栈:


蛮力法(brute force):

直接基于问题的 描述和所涉及的概念定义的进行算法 设计,简单而直接。
使用蛮力法… :
(1) 蛮力法所能解决的问题跨越的领域非常广泛。
(2) 对于一些重要的问题,运用蛮力策略可以设计出具备一
定实用价值的算法,并且不用限制实例的规模。
(3) 当要解决的问题实例不多并且可以接受蛮力法的运算速
度时,蛮力法的设计代价通常较为低廉。
(4) 蛮力算法可以作为衡量其它算法的准绳,服务于研究或
教学。
 枚举法的算法框架可表示如下:
(1) 依据问题,设定枚举范围
(2) 找出约束条件,建立计算模型
(3) 利用计算模型在枚举范围内搜索可能的解。

【例4-1】链环数字对

输入n个数字(在0与9之间),然后统计出这组数中
相邻两个数字组成的链环数字对出现的次数。如:n=20,输
入为:0 1 5 9 8 7 2 2 2 3 2 7 8 7 8 7 9 6 5 9,则输
出为(7,8)=2, (8,7)=3,(7,2)=1,(2,7)=1,(2,2)=2,(2,3)=1,(3,2)=1。

问题分析

设置一个二维数组,让其两个下标代表输入的数字对,
每输入一个数字对,则把对应下标的数组元素加1,若xi表
示输入的数字,在输入xi ,xi+1,xi+2时,a[xi ,xi+1] =a[xi ,xi+1]+1、
a[xi+1,xi+2] =a[xi+1,xi+2]+1,依此类推。

计算模型

(1) 计数:输入任意两数字xi xi+1,则a[xi ,xi+1]++。
(2) 统计:若a[xi ,xi+1]≥1和a[xi+1,xi]≥1均大于1,表示有链
环数字对(xi ,xi+1)( xi+1,xi),输出。
(2) 存储
输入n个数字(在0与9之间),然后统计出这组数中相邻两个数 字组成的链环数字对出现的次数。
算法设计与描述 算法分析
输入:n,x1,x2,....,xn
输出:有效数字对

pair_digital(int n):

{

int a[10,10] <- {0} ;

input( x1 );

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

{
                input(x2);

a[x1,x2] <- a[x1, x2]+1;

x1<-x2;

}

for ( i<-0 ;i<10;i<-i+1 )

{

for(j<-0 ;j<=i;j<-j+1)

{

if(a[i,j]!=0  and a[j,i]!=0)

if(i!=j)

output( (i,j) = a[i,j] , (j,i) =a[j,i ]  );

else output( (i,j)=a[i,j]);//对角线元素

}
        }

}

(1)输入n个元素,计数矩阵10*10

(2)核心语句包括两部分:统计和输出

(3)

当n>>100时,是上面的部分占比较大。

代码:

#include<iostream>
using namespace std;int main()
{int n=20;int x[n]={0, 1, 5, 9 ,8 ,7, 2 ,2 ,2 ,3, 2, 7 ,8, 7 ,8 ,7, 9, 6, 5 ,9};int a[10][10]={0,0};for(int i=0;i<10;i++){for(int j=0;j<10;j++){a[i][j]=0;}}for(int i=1;i<n;++i){a[x[i-1]][x[i]] = a[x[i-1]][x[i]]+1;
//      cout<<a[x[i-1]][x[i]]<<endl;}for(int i=0;i<10;++i){for(int j=0;j<=i;++j){if(a[i][j]!=0 && a[j][i]!=0){if(i!=j){cout<<"("<<i<<","<<j<<")="<<a[i][j]<<"\t";cout<<"("<<j<<","<<i<<")="<<a[j][i]<<endl;}else{cout<<"("<<i<<","<<j<<")="<<a[i][j]<<endl;}}}}return 0;
}
/*(2,2)=2
(3,2)=1 (2,3)=1
(7,2)=1 (2,7)=1
(8,7)=3 (7,8)=2
*/

【例4-2】解数字迷:

问题分析

(1) 枚举测试,五位数范围99999~30000。时间复杂度为 99999-30000+1=70000次。
(2) 构造式的枚举法—乘法:
A的取值:3~9
B、C的取值:0~9
构造满足条件的五位数,与A相乘,判断求解。时间复杂
度为7*10*10=700。
(3) 构造式的枚举法—除法:
D的取值:1~9
A的取值:3~9
利用DDDDDD/A求解,时间复杂度为9*7=63。

思考题:ACM预测:

问题分析:

甲乙丙丁四位学生取得名次4*3*2*1种可能,一共是n!种可能,但是在约束条件下只有一种可能是正确的。因此用多重循环对每种可能的情况进行遍历,当符合条件时跳出循环。

计算模型:

甲乙丙丁设为int a,b,c,d;所存数字代表名次。

(1)a可能的名次是从1到4, for(a=1;a<=4;++a)

(2)b可能的名次是从1到4,for(b=1;b<=4;++b),且不等于a的名次(b!=a),

(3)c可能的名次是从1到4,for(c=1;c<=4;++c),且不等于a,b的名次(c!=a&& c!=b)

(4)d可能的名次是除abc之外的剩下名次,也就是10-a-b-c;

(5)在此种可能下 若三位老师的预测都是一真一假 ((a==1)+(b==3)==1)&&( (c==1)+(d==4 )==1)&&((a==3)+(d==2)==1 ),则成立。

算法分析:

算法设计与描述 算法分析
输入:学生人数n,三位老师的预测
输出:正确排名

Assume():

{

int a,b,c,d;
    for(a<-1;a<=4;++a)
    {
        for(b<-1;b<=4;++b)
        {
            if(a!=b)
                for(c<-1;c<=4;++c)
                {
                    if(c!=a&& c!=b) {
                        d <- 10-a-b-c;
                        if(((a==1)+(b==3)==1)&&( (c==1)+(d==4 )==1)&&((a==3)+(d==2)==1 )   )
                        {
                            cout<<"甲:"<<a<<"乙:"<<b<<"丙:"<<c<<"丁:"<<d<<endl;
                        }
                    }
                }
        }
    }

}

(1)输入人数 n=4,

(2)核心语句:判断是否符合条件。

(3)最坏情况是每种情况都遍历。T(n)=n!

代码

#include<bits/stdc++.h>
using namespace std;/*
ACM大赛预测计算名次
Z:甲第一,乙第三。
L:丙第一,丁第四。
T:丁第二,甲第三。 都只说对一半
计算名次
*/int main()
{//假设甲乙丙丁是ABCDint a,b,c,d;for(a=1;a<=4;++a){for(b=1;b<=4;++b){if(a!=b)for(c=1;c<=1;++c){d=10-a-b-c;if(((a==1)+(b==3)==1)&&( (c==1)+(d==4 )==1)&&((a==3)+(d==2)==1 )   ){cout<<"甲:"<<a<<"乙:"<<b<<"丙:"<<c<<"丁:"<<d<<endl;break;}}}}return 0;
}
//甲:4乙:3丙:1丁:2

【例4-3】输出玫瑰矩阵,其为n*n的方阵,特征如下所示:

问题分析:

左侧:a[j, i] <- k, k <- k+1, j <- j+1;

底侧:a[n-i-1, j] <- k, k <- k+1,j <- j+1;

右侧:a[j, n-i-1] <- k, k <- k+1,j <- j-1;

顶侧:a[i, j] <- k, k <- k+1,j <- j-1;

计算模型

设圈数为i,变化量为j,矩阵元素值为k且k <- 1

左侧:a[j, i] <- k, k <- k+1, j <- j+1; 其中,j∈[i, n-i-1)

底侧:a[n-i-1, j] <- k, k <- k+1, j <- j+1; 其中,j∈[i, n-i-1)

右侧:a[j, n-i-1] <- k, k <- k+1, j <- j-1; 其中,j∈[n-i-1, i)

顶侧:a[i, j] <- k, k <- k+1, j <- j-1; 其中,j∈[n-i-1, i)

圈数控制:i=n/2(取整),对于奇数项,最后一圈1个元素

思考题:

算法2:

下标

(0,0)   (0,1)   (0,2)   (0,3)
(1,0)   (1,1)   (1,2)   (1,3)
(2,0)   (2,1)   (2,2)   (2,3)
(3,0)   (3,1)   (3,2)   (3,3)

问题分析
每半圈元素值的增长规律变换一次
设增量t,每半圈变换一次t <- -t .
设矩阵边长为i,每半圈的元素个数是2*(i-1)个,hc为记数变
量,则1≤hc<=2*i-1,前1/4圈是1≤hc<=i-1,后1/4是i≤hc<=2*i-2,
若让hc整除于i,则前1/4圈结果为0,后1/4结果为1,可表示为:index <- hc/i, hc <- hc+1;。
计算模型
设s[]为矩阵下标, 其中,行下标
s[1] ,列下标s[0]。s的下标为index。t为
下标增量,初值t <- 1。矩阵元素值为
k∈[1, n*n]。 hc>=2*i-2指超过半圈,当k
增长到n*n时,结束。注意s[0]的初值,
下标是从进入循环就开始运算的。

  • index<- hc/i+1
  • hc<- hc+1
  • hc∈[1,2*i-1]
  • s[index]<-s[index]+t
  • a[s[1],s[0]]<- k , k<- k+1
  • i<- i-1 ,t<- -t 当hc>2*i-1

算法分析:

算法设计与描述 算法分析
输入:输入规模为n*n
输出:类玫瑰矩阵

void RP(int n)
{
    k<- 1,i<-n,t<-1;
    s[0]<-  -1,s[1] <- 0;
    while(k<=n*n)
    {
        for(int hc <- 1;hc<=2*i-1;++hc)
        {
            index <- hc/(i+1);
            s[index]<-s[index]+t;
            a[s[1]][s[0]]<-k;
            ++k;
        }
        i--;
        t=-t;
    }

}

(1)输入规模n*n,

(2)核心语句:半圈数据摆放。

(3)实际计算次数是k 也就是n*n

T(n)=C*k =C*n*n =

代码:

#include<iostream>
using namespace std;void RP(int n)
{int s[2];int a[n][n];int k=1,i=n,t=1;s[0]=-1,s[1]=0;while(k<=n*n){for(int hc=1;hc<=2*i-1;++hc){int index=hc/(i+1);s[index]=s[index]+t;a[s[1]][s[0]]=k;++k;}i--;t=-t;}for(int i=0;i<n;i++){for(int j=0;j<n;++j){cout<<a[i][j]<<"\t";}cout<<endl;}}int main()
{int n=4;RP(n);return 0;
} 

问题分析:

n是矩阵边长。

用 i 表示圈 ,j代表圈内下标变化量:

顶侧:a[i,j]<-k ,k<- k+1 , j<- j+1 ;//横坐标不变 纵坐标++

右侧:a[j,n-i-1] ,k<- k+1 , j<- j-1 ;//纵坐标不变,横坐标--

底侧:a[i,j]<-k ,k<- k+1 , j<- j-1 ;//横坐标不变 纵坐标--

左侧:a[j,n-i-1] ,k<- k+1 , j<- j+1 ;//纵坐标不变,横坐标++

计算模型:

n是矩阵边长。

用 i 表示圈 ,j代表圈内下标变化量,矩阵元素k 且k<-1 .

顶侧:a[i,j]<-k ,k<- k+1 , j<- j+1 ;其中 j∈[ i,

右侧:a[j,n-i-1] ,k<- k+1 , j<- j-1 ;//纵坐标不变,横坐标--

底侧:a[i,j]<-k ,k<- k+1 , j<- j-1 ;//横坐标不变 纵坐标--

左侧:a[j,n-i-1] ,k<- k+1 , j<- j+1 ;//纵坐标不变,横坐标++

二、穷举查找

有一些求最优解的问题经过抽象,可以转换为组合优
化问题,使用蛮力法来求解是一种简单的方法,称之为穷
举查找(exhaustive search)。

【例4-4】旅行商问题(traveling salesman problem,TSP)——排列树

一个旅行商由某市出发,经过所有给定的n个城市后,再
回到出发的城市。除了出发的城市外,其它城市只经过一
回。这样的回路可能有多个,求其中路径成本最小的回路。

问题分析

计算模型

(1) 存储 图G(V, E)。以邻接矩阵的方式存储,设计如下:

(2)计算 设起始点下标为0

 生成排列树。设解空间为a,则其解空间的计算过程可描述为:

 求回路代价。设sumi 是并入第i个结点的代价 :

sumi并入第i个结点的代价= sum_i-1代入第i-1个结点的代价 + 边(i-1到i)

代码:

#include<iostream>
using namespace std;int n=4;
int edge[4][4]={0,8,5,4,
8,0,7,3,
5,7,0,1,
4,3,1,0};
int vertex[4]={'a','b','c','d'};int a[]={0,1,2,3};//解空间
int minvalue=1000;//当前最小值
int path[4]={0};//当前解的路径
int minpath[4]={0};//最优解 void output(int a[])
{for(int i=0;i<n;++i){cout<<a[i]<<'\t';}cout<<a[0];cout<<endl;
}
int cost()
{//先求从0 到第一个点的距离 int i,sum=edge[0][a[0]];for(i=1;i<n;++i){sum=sum+edge[a[i-1]][a[i]];} sum=sum+ edge[a[i-1]][0];//再加上 回到0的距离 return sum;
}
void copypath(int s[])
{int i;cout<<"copypath:";for(i=0;i<n;++i){s[i]=a[i];cout<<s[i]<<"\t"; }cout<<endl;
}void EnumSalesMan(int i)
{cout<<endl<<"EnumSalesMan:"<<i<<endl;int k,temp;if(i==n-1)//遍历到最后一个点 {cout<<"i==n-1"<<endl;if(minvalue>cost())//当前解的权值{minvalue=cost();//最小路径cout<<"cost():"<<minvalue<<endl;copypath(minpath);} }else{for(k=i;k<n;++k) {cout<<"sawp  i:"<<i<<" "<<a[i]<<" k:"<<k<<" "<<a[k]<<endl;//交换 i和 k  全排列 temp=a[i];a[i]=a[k];a[k]=temp;//找下一条路径 EnumSalesMan(i+1);//恢复之前的顺序 temp=a[i];a[i]=a[k];a[k]=temp;}}}
int main()
{EnumSalesMan(0); output(a);cout<<"minvalue:"<<minvalue<<endl;return 0;
}

1.蛮力字符比较

蛮力字符匹配算法:

设T[0...n-1] ,P[0..m-1]

文本串的第一个字符 从模板串的第一个字符到最后一个字符进行比较,耗时m

若不成功,则从文本串第二个字符再开始 与模板串所有字符进行比较。

最坏情况下 需要n次比较,每次耗时m
T(n,m)=n*m=O(n*m);

2.旅行路线 效率类型

T(n)=O( (n-1)! )

3.城市个数

用太湖之光计算城市个数

每秒十亿次 10^10 十位数

1小时=60*60s=3.6*10^13   约15个城市

24小时= 24*3.6*10^13 =8.64*10^14 约16个城市

1年=365*8.64*10^14=3.1536*10^17  约19个

100年  =3.1536*10^19  约33个

【例4-5】背包问题。——组合森林

给定n个重量为w1 , w2 ,…wn ,价值为v1 ,
v2 ,…vn 的物品和一个承重为W的背包,求将这些物品中的
某些装入背包中,在不超出重量W的情况下,价值最高的
装法

问题分析

运筹学:先列出目标。在列出方程(约束条件,可能很少)

(砍枝过程)

背包最多能装10公斤物品,按照{重量,价值}表示法,
图中物品依次为a0 ={7, 42}, a1 ={3, 12}, a2 ={4, 40}, a3 ={5, 25}。

 计算模型

1)重量和价值的累加
sum_v= sum_v ± a[i].v; //有加减 有放有拿
sum_w=sum_w ± a[i].w
2)递归方程。
递归结束的条件:sum_w>W
递归的方程为:knaps(i)=knaps(i+1) i∈[0,n-1]

图的搜索

图的两个重要的遍历算法:深度优先查找(depth-first search,
DFS)和广度优先查找(breadth-frist search, BFS),是穷举查找的
重要应用之一。
深度优先查找(depth-first search, DFS)

邻接链表

【例4-6】迷宫问题。如图4-4(1)所示,图中方格内标为0的
为通路,标为1墙。(0,0)为迷宫入口,(7,7)为迷宫出口,请
查出由(0,0)到(7,7)的路径。

每一步都要判断是否在边or角上。=》简化:加墙

思考题

1.广度优先 三壶问题

!!!终于做出来了,感谢zy

#include<bits/stdc++.h>using namespace std;/*
一个8品
3 5
make 4 思想引导:
可以将每一种状态看做节点
然后广度优先,边遍历边建图
将每一个节点和他的状态前缀压到图容器里面,
然后遍历容器
走到其中有一个为四的时候从该节点开始依次前推得出整个路径实际:
穷举+一点点回溯的感觉 */typedef struct node{int x,y,z;struct node * pre;
}node;queue<node*>q;//队列
set<int> h;
node *p2;
void show(node *p)
{cout<<"("<<p->x<<","<<p->y<<","<<p->z<<")"<<endl;
}bool pan(node *p)
{
//  cout<<"pan";
//  show(p);if(p->x==4 || p->y==4 ||p->z==4)return true;else return false;
}void bfs()
{node* p=new node;p->x=8;p->y=0;p->z=0;//初始状态p->pre=NULL;//入队q.push(p);
//  node *p1;while(!q.empty() ){//队首元素 node *p1=q.front();if(pan(p1))return;//结束循环 int x=p1->x;int y=p1->y;int z=p1->z;q.pop();//当前状态是否被访问过 if(h.find(x*100+y*10+z) !=h.end())//找到 continue;//跳过 else h.insert(x*100+y*10+z);
//      show(p1);//进行尝试 //1.x->y if(x>0 && y<5 ){p2=new node;if(x+y>5)//会溢出{p2->x=(x + y -5);p2->y=5; }else{p2->x=0;p2->y=y+x;}p2->z=z;p2->pre=p1;q.push(p2); if(pan(p2))return;//结束} //x-zif(x>0 && z<3){p2=new node;if(x+z>3)//会溢出{p2->x=(x+z-3);p2->z=3;}else{p2->x=0;p2->z=x+z;}p2->y=y; p2->pre=p1;q.push(p2); if(pan(p2))return;//结束}//y-x if(y>0 ){p2=new node;p2->x=y+x;p2->y=0;p2->z=z;p2->pre=p1;q.push(p2); if(pan(p2))return;//结束}//y-zif(y>0 && z<3){p2=new node;if(y+z>3)//会溢出{p2->y=(y+z-3);p2->z=3;}else{p2->y=0;p2->z=y+z;}p2->x=x; p2->pre=p1;q.push(p2); if(pan(p2))return;//结束}//z-x if(z>0 ){p2=new node;p2->z=0;p2->x=x+z;p2->y=y;p2->pre=p1;q.push(p2); if(pan(p2))return;//结束}//z-yif(z>0 && y<5){p2=new node;if(y+z>5)//会溢出{p2->y=5;p2->z=(z+y-5);}else{p2->z=0;p2->y=y+z;}p2->x=x; p2->pre=p1;q.push(p2); if(pan(p2))return;//结束}}
}int main()
{bfs();node *p=q.front();cout<<"res:"<<endl;show(p2);//需要单独把4 输出 while(p){show(p);p=p->pre;}return 0;
}
/*
res:
(1,4,3)
(5,0,3)
(6,0,2)
(6,2,0)
(3,2,3)
(3,5,0)
(8,0,0)
*/

2.广度优先 迷宫最优解

是否“广度优先第一个解就是最优解” ?

广度优先的遍历顺序也是决定因素之一,例如这个迷宫,如果是先向右下遍历 那么找到第一条应该就是最优解。

代码:队列(自)

#include<iostream>
#include<queue>
#include<cstdlib>
using namespace std;
//迷宫 队列 int m[10][10]={
1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,1,
1,0,1,1,1,1,0,1,0,1,
1,0,0,0,0,1,0,1,0,1,
1,0,1,0,0,0,0,1,0,1,
1,0,1,0,1,1,0,1,0,1,
1,0,1,0,0,0,0,1,1,1,
1,0,1,0,0,1,0,0,0,1,
1,0,1,1,1,1,1,1,0,1,
1,1,1,1,1,1,1,1,1,1,} ;typedef struct po{int x,y;struct po * pre;//
}po;
//用链表存储路径queue<po*> q;//队列
int fx[]={-1,1,0,0};//方向
int fy[]={0,0,-1,1};//方向
int x=1,y=1;//起点
po *p; void bfs()//广度优先
{m[x][y]=3;//已访问p=new po;p->x=x;p->y=y;p->pre=NULL;q.push(p);//起点入队 while(!q.empty() ){po * p1=q.front();//队首元素 q.pop();//对该结点进行尝试,共四种可能for(int i=0;i<4;i++){po* pnew=new po;pnew->pre=NULL; pnew->x =p1->x + fx[i];pnew->y = p1->y+ fy[i];//该点是否可以走if(m[pnew->x][pnew->y] ==0 ) //未走过{m[pnew->x][pnew->y]=3;//已走过//保存两点之间的关系 pnew->pre=p1;q.push(pnew);//新结点入队 }if(pnew->x==8 && pnew->y==8)//结束条件 return;//结束 } }
} int main()
{bfs(); po * p=q.front();while(p){ cout<<p ->x<<","<<p ->y<<endl;p=p->pre;}return 0;
}

代码00:队列

#include<iostream>
#include<queue>
#include <cstdlib>
using namespace std;
/*
队列 先入先出
每次都是对最近的点也就是偏下偏右的点  进行遍历
因而更容易找到最短路径 */
int maze[10][10]={
1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,1,
1,0,1,1,1,1,0,1,0,1,
1,0,0,0,0,1,0,1,0,1,
1,0,1,0,0,0,0,1,0,1,
1,0,1,0,1,1,0,1,0,1,
1,0,1,0,0,0,0,1,1,1,
1,0,1,0,0,1,0,0,0,1,
1,0,1,1,1,1,1,1,0,1,
1,1,1,1,1,1,1,1,1,1,} ;
//maze[x][y]=0表示通路,maze[x][y]=1表示墙,
//maze[x][y]=2表示“死”路,maze[x][y]=3表示已走过。
typedef struct place{int x,y;struct place *pre;
}place,*P;void mazesearch_BFS()
{queue<place *> q;P p1,p2;p1=(place *)malloc(sizeof(place));p2=(place *)malloc(sizeof(place));//行走的相对路径 int fx[4]={-1,1,0,0};//方向 int fy[4]={0,0,-1,1};//方向 int nextx=1,nexty=1;//起点 maze[nextx][nexty]=3; //起点已走过 //起点p1->x=nextx;p1->y=nexty;p1->pre=NULL;q.push(p1);//终点入队 //队列 先入先出// while(!q.empty()){p2=q.front();//队首元素cout<<"front:"<<p2->x<<" "<<p2->y<<endl;q.pop();//出队if(p2->x==8 && p2->y==8){//终点 cout<<"@end"<<endl;break;}for(int j=0;j<4;++j)//从该点p2沿四个方向探索 {//行走过程 nextx= p2->x+fx[j];nexty= p2->y+fy[j];cout<<"is:"<<p2->x<<" "<<p2->y<<endl;if(maze[nextx][nexty]==0){//表示和p2相邻有路可走且没走过 P p3=(place *)malloc(sizeof(place));p3->x=nextx;p3->y=nexty;maze[nextx][nexty]=3;//标记已走过cout<<"bis:"<<p2->x<<" "<<p2->y<<endl;p3->pre=p2;//标记其前驱 即刚出队的点 cout<<"ais:"<<p2->x<<" "<<p2->y<<endl;q.push(p3);//入队 //                cout<<p3->x<<" "<<p3->y<<"@@@@"<<p3->pre->x<<" "<<p3->pre->y<<endl;cout<<p3->x<<" "<<p3->y<<"@@@@"<<p2->x<<" "<<p2->y<<endl;if(nextx==8 &&nexty==8)//结束 {cout<<"@end"<<endl;break;//但只是跳出for循环 没有结束while循环 }}}}//while//对手元素 if(p2->x==8 && p2->y==8){//p2是终点 cout<<"("<<p2->x<<","<<p2->y<<")"<<"  ";while(p2->pre){p2=p2->pre;cout<<"("<<p2->x<<","<<p2->y<<")"<<"  ";}}}
int main()
{mazesearch_BFS();return 0;
}
/*(8,8)  (7,8)  (7,7)  (7,6)  (6,6)  (6,5)  (6,4)  (6,3)  (5,3)  (4,3)  (3,3)  (3,2)  (3,1)  (2,1)  (1,1)*/

01:栈

#include<iostream>
#include<queue>
#include<stack>
#include <cstdlib>
using namespace std;
/*
用stack 后入先出
也就是每次都是对 左上 的点优先遍历
更多冤种路径 队列 先入先出
每次都是对最近的点也就是偏下偏右的点  进行遍历
因而更容易找到最短路径 */int maze[10][10]={
1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,1,
1,0,1,1,1,1,0,1,0,1,
1,0,0,0,0,1,0,1,0,1,
1,0,1,0,0,0,0,1,0,1,
1,0,1,0,1,1,0,1,0,1,
1,0,1,0,0,0,0,1,1,1,
1,0,1,0,0,1,0,0,0,1,
1,0,1,1,1,1,1,1,0,1,
1,1,1,1,1,1,1,1,1,1,} ;
//maze[x][y]=0表示通路,maze[x][y]=1表示墙,
//maze[x][y]=2表示“死”路,maze[x][y]=3表示已走过。
int fx[]={-1,1,0,0};
int fy[]={0,0,-1,1};
typedef struct p{int x,y;struct p* next;
}point;void bfs()
{stack<point*>s;point *head=new point,*p;int x=1,y=1;head->x=x;head->y=y; head->next=NULL;maze[x][y]=3;//已访问s.push(head);int flag=0;while(!s.empty() ){p=s.top();s.pop();cout<<"front:"<<p->x<<" "<<p->y<<endl;for(int i=0;i<4;++i){y=p->y+fy[i];x=p->x+fx[i];if(maze[x][y]==0){cout<<x<<" "<<y<<endl; maze[x][y]=3;point * newp=new point;newp->x=x;newp->y=y;newp->next=p;s.push(newp);if(x==8 && y==8){flag=1;break;} }}if(flag)break;} p=s.top();while(p){cout<<"("<<p->x<<","<<p->y<<")"<<"  ";p=p->next;}
}int main()
{bfs();return 0;
}
/*(8,8)  (7,8)  (7,7)  (7,6)  (6,6)  (6,5)  (6,4)  (6,3)  (5,3)  (4,3)  (4,4)  (4,5)  (4,6)  (3,6)  (2,6)  (1,6)  (1,5)  (1,4)  (1,3)  (1,2)  (1,1)
*/

02栈:

#include<iostream>
#include<queue>
#include<stack>
#include <cstdlib>
using namespace std;
/*
用stack 后入先出
也就是每次都是对 左上 的点优先遍历
更多冤种路径 队列 先入先出
每次都是对最近的点也就是偏下偏右的点  进行遍历
因而更容易找到最短路径 当然 这是由上下左右搜索的顺序决定的
*/int maze[10][10]={
1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,0,1,
1,0,1,1,1,1,0,1,0,1,
1,0,0,0,0,1,0,1,0,1,
1,0,1,0,0,0,0,1,0,1,
1,0,1,0,1,1,0,1,0,1,
1,0,1,0,0,0,0,1,1,1,
1,0,1,0,0,1,0,0,0,1,
1,0,1,1,1,1,1,1,0,1,
1,1,1,1,1,1,1,1,1,1,} ;
//maze[x][y]=0表示通路,maze[x][y]=1表示墙,
//maze[x][y]=2表示“死”路,maze[x][y]=3表示已走过。
int fx[]={0,0,-1,1};
int fy[]={-1,1,0,0};
typedef struct p{int x,y;struct p* next;
}point;void bfs()
{stack<point*>s;point *head=new point,*p;int x=1,y=1;head->x=x;head->y=y; head->next=NULL;maze[x][y]=3;//已访问s.push(head);int flag=0;while(!s.empty() ){p=s.top();s.pop();cout<<"front:"<<p->x<<" "<<p->y<<endl;for(int i=0;i<4;++i){y=p->y+fy[i];x=p->x+fx[i];if(maze[x][y]==0){cout<<x<<" "<<y<<endl; maze[x][y]=3;point * newp=new point;newp->x=x;newp->y=y;newp->next=p;s.push(newp);if(x==8 && y==8){flag=1;break;} }}if(flag)break;} p=s.top();while(p){cout<<"("<<p->x<<","<<p->y<<")"<<"  ";p=p->next;}
}int main()
{bfs();return 0;
}
/*01:(8,8)  (7,8)  (7,7)  (7,6)  (6,6)  (6,5)  (6,4)  (6,3)  (5,3)  (4,3)  (4,4)  (4,5)  (4,6)  (3,6)  (2,6)  (1,6)  (1,5)  (1,4)  (1,3)  (1,2)  (1,1)02:(8,8)  (7,8)  (7,7)  (7,6)  (6,6)  (6,5)  (6,4)  (6,3)  (5,3)  (4,3)  (3,3)  (3,2)  (3,1)  (2,1)  (1,1)*/

裴蜀定理:

设 d=gcd(a,b) ,最大公约数

那么对于方程 ax+by=d,一定存在一组整数解。并且对于方程 ax+by=z,如果满足 z%d==0,那么方程一定有整数解,否则无整数解。

也就是若z是最大公约数的整数倍。

代码:

int gcd(int x,int y)
{return y==0? x  :gcd( y,x%y);
}bool pan(int x,int y,int z)
{return z==0 || (x+y>=z && gcd(x,y)==0 );
}

当容量为x、y的两水壶可以获得z升的水,则有ax+by=z,其中a、b均为整数。证明:

以x=3,y=5为例,当有ax+by=z,a=-2,b=2,表示需要将壶2接满两次水,壶1满壶状态下倒空两次:将壶2接满第一次,有5升水;壶2倒入壶1,壶2剩余2升水,壶1第一次倒空;将壶2的水倒入壶1,壶1有2升水,壶2空;将壶2接满第二次;将壶2的水倒入壶1,壶2剩余4升水;将壶1第二次倒空;于是就剩下了壶2的4升水.

【算法设计zxd】第四章蛮力法 1.枚举法 02穷举查找相关推荐

  1. 【算法设计zxd】第一章 算法基础 1.基本概念+最大公约数

    目录 一.基本概念: 例1-1:求最大公约数 问题分析: 计算模型: 1) 穷举法 2) 欧几里德算法(辗转相除法) 算法设计与描述: 算法分析-效率: 1) 穷举法: 2) 欧几里德算法分析-渐近法 ...

  2. 【算法设计zxd】第一章 算法基础 4.设计工具【三角矩阵,】

    目录 1. 循环设计 (1) 设计思维 自底向上的设计(Down - Top Design) 自顶向下的设计(Top-Down Design) (2)挖掘内在规律构建计算模型 [例1-3]设计算法,输 ...

  3. 【算法设计zxd】第一章 算法基础 5.基本数据结构

    目录 思考题:学过的数据结构及其特点 (1)线性数据结构 (2) 树 (2) 树-二叉树 (3) 图 (3) 图-表示方法.邻接矩阵法 (3) 图-表示方法.邻接表 思考题:学过的数据结构及其特点 线 ...

  4. AcWing提高算法课Level-3 第四章 高级数据结构

    AcWing提高算法课Level-3 第四章 高级数据结构 并查集 AcWing 1250. 格子游戏1167人打卡 AcWing 1252. 搭配购买1064人打卡 AcWing 237. 程序自动 ...

  5. 《算法笔记》第四章笔记

    <算法笔记>第四章 排序 排序算法的思想都比较简单,而且c++可以直接用sort函数进行排序,一般不会直接写排序代码 归根到底就是每轮处理一个数据,n个数据只需处理n-1次即可变得有序 选 ...

  6. 算法设计与分析第一章递推算法

    算法设计与分析 第一章 递推算法 1.概述 在**已知条件**和**所求问题**之间总存在着某种相互联系的关系,如果可以找到前后过程之间的数量关系(即递推式),那么,从**问题出发逐步推到已知条件** ...

  7. 【算法设计zxd】第3章 迭代法 杨辉三角,穿越沙漠,内存移动,竖式相乘(阶乘)

    目录 迭代:(辗转法)        一种 不断用变量的旧值递推新值的过程 [例3-1] 输出如图的杨辉三角形. [例3-2]穿越沙漠问题 [例3-2]内存移动问题 [例3-4]编程求当n<=1 ...

  8. 【算法设计zxd】第3章迭代法03 线性代数方程

    线性代数方程:  设线性代数方程组具有如下特征:  算法框架 (1)设置线性代数方程组的初值X=(x1,-,xn-1 ,xn): (2)构造迭代方程xi=gi (X)   (i=1,-,n-1,n ...

  9. 【算法设计zxd】第2章 算法分析实例 递归非递归——交换,n阶乘,矩阵乘法,汉诺塔,二路归并,

    目录 非递归形式算法分析: 递归形式算法分析: [例2-9]交换a和b的值. 非递归 [例2-10]求n! 非递归: 思考题:韩信点兵 [例2-11]对于任意给定的n阶方阵A和B,求A×B的积C并且 ...

最新文章

  1. Nagios 监控实例部署
  2. linux配置nginx虚拟目录
  3. python中文解释-python注释不能识别中文
  4. BaaS后端即服务 - 概念篇
  5. 6 四大组件之Service
  6. 技巧:在 C/C++中如何构造通用的对象链表
  7. 手机端本地图片或者拍照的上传功能
  8. 拒绝yyds洗脑,我是Pro!
  9. Android JNI学习(四)——JNI的常用方法的API
  10. Python编写的数字拼图游戏(含爬山算法人机对战功能)
  11. .net core平台使用遇到的坑
  12. VS2017 CUDA编程学习12:CUDA流
  13. win10系统下载 Ghost Win10 RS1 1607 32位纯净3月版
  14. 说一下html5 drag api,HTML5 DragAPI
  15. 计算机组成原理下列数中最小的数位,计算机组成原理试题(四)
  16. Web前端-HTML
  17. SQLserver提权
  18. H5游戏视力测试-玩到第八关都是大神
  19. 硬件产品开发:外包五要素和外包地图
  20. 电脑C语言软件怎样拷贝到u盘,禁止U盘复制电脑文件、禁止电脑文件复制到U盘、禁止复制计算机文件到U盘的方法...

热门文章

  1. 2022年全球与中国EV继电器市场现状及未来发展趋势
  2. 讲讲简单的电源隔离和信号地,电源地的处理
  3. docker-compose.yml修改volumes后重启不生效
  4. Andriod小项目——在线音乐播放器
  5. 网站渗透测试之常见漏洞排行
  6. Google前员工创办社交推荐引擎Stamped,已获A轮投资
  7. UltraISO 制作系统启动盘教程
  8. 黄金矿工两百行基于Easyx
  9. 让我们跳过中年危机,直接聊聊如何善终
  10. 任正非告别荣耀讲话—-陌生的感动