【算法设计zxd】第四章蛮力法 1.枚举法 02穷举查找
目录
蛮力法(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):
【例4-1】链环数字对
问题分析
计算模型
算法设计与描述 | 算法分析 |
输入:n,x1,x2,....,xn | |
输出:有效数字对 | |
pair_digital(int n): { int a[10,10] <- {0} ; input( x1 ); for( i<- 1; i<n;i<-i+1) { 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】解数字迷:
问题分析
思考题: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; } |
(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)
- 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) } |
(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 ;//纵坐标不变,横坐标++
二、穷举查找
【例4-4】旅行商问题(traveling salesman problem,TSP)——排列树
问题分析
计算模型
(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】背包问题。——组合森林
问题分析
运筹学:先列出目标。在列出方程(约束条件,可能很少)
(砍枝过程)
计算模型
图的搜索
邻接链表
思考题
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穷举查找相关推荐
- 【算法设计zxd】第一章 算法基础 1.基本概念+最大公约数
目录 一.基本概念: 例1-1:求最大公约数 问题分析: 计算模型: 1) 穷举法 2) 欧几里德算法(辗转相除法) 算法设计与描述: 算法分析-效率: 1) 穷举法: 2) 欧几里德算法分析-渐近法 ...
- 【算法设计zxd】第一章 算法基础 4.设计工具【三角矩阵,】
目录 1. 循环设计 (1) 设计思维 自底向上的设计(Down - Top Design) 自顶向下的设计(Top-Down Design) (2)挖掘内在规律构建计算模型 [例1-3]设计算法,输 ...
- 【算法设计zxd】第一章 算法基础 5.基本数据结构
目录 思考题:学过的数据结构及其特点 (1)线性数据结构 (2) 树 (2) 树-二叉树 (3) 图 (3) 图-表示方法.邻接矩阵法 (3) 图-表示方法.邻接表 思考题:学过的数据结构及其特点 线 ...
- AcWing提高算法课Level-3 第四章 高级数据结构
AcWing提高算法课Level-3 第四章 高级数据结构 并查集 AcWing 1250. 格子游戏1167人打卡 AcWing 1252. 搭配购买1064人打卡 AcWing 237. 程序自动 ...
- 《算法笔记》第四章笔记
<算法笔记>第四章 排序 排序算法的思想都比较简单,而且c++可以直接用sort函数进行排序,一般不会直接写排序代码 归根到底就是每轮处理一个数据,n个数据只需处理n-1次即可变得有序 选 ...
- 算法设计与分析第一章递推算法
算法设计与分析 第一章 递推算法 1.概述 在**已知条件**和**所求问题**之间总存在着某种相互联系的关系,如果可以找到前后过程之间的数量关系(即递推式),那么,从**问题出发逐步推到已知条件** ...
- 【算法设计zxd】第3章 迭代法 杨辉三角,穿越沙漠,内存移动,竖式相乘(阶乘)
目录 迭代:(辗转法) 一种 不断用变量的旧值递推新值的过程 [例3-1] 输出如图的杨辉三角形. [例3-2]穿越沙漠问题 [例3-2]内存移动问题 [例3-4]编程求当n<=1 ...
- 【算法设计zxd】第3章迭代法03 线性代数方程
线性代数方程: 设线性代数方程组具有如下特征: 算法框架 (1)设置线性代数方程组的初值X=(x1,-,xn-1 ,xn): (2)构造迭代方程xi=gi (X) (i=1,-,n-1,n ...
- 【算法设计zxd】第2章 算法分析实例 递归非递归——交换,n阶乘,矩阵乘法,汉诺塔,二路归并,
目录 非递归形式算法分析: 递归形式算法分析: [例2-9]交换a和b的值. 非递归 [例2-10]求n! 非递归: 思考题:韩信点兵 [例2-11]对于任意给定的n阶方阵A和B,求A×B的积C并且 ...
最新文章
- Nagios 监控实例部署
- linux配置nginx虚拟目录
- python中文解释-python注释不能识别中文
- BaaS后端即服务 - 概念篇
- 6 四大组件之Service
- 技巧:在 C/C++中如何构造通用的对象链表
- 手机端本地图片或者拍照的上传功能
- 拒绝yyds洗脑,我是Pro!
- Android JNI学习(四)——JNI的常用方法的API
- Python编写的数字拼图游戏(含爬山算法人机对战功能)
- .net core平台使用遇到的坑
- VS2017 CUDA编程学习12:CUDA流
- win10系统下载 Ghost Win10 RS1 1607 32位纯净3月版
- 说一下html5 drag api,HTML5 DragAPI
- 计算机组成原理下列数中最小的数位,计算机组成原理试题(四)
- Web前端-HTML
- SQLserver提权
- H5游戏视力测试-玩到第八关都是大神
- 硬件产品开发:外包五要素和外包地图
- 电脑C语言软件怎样拷贝到u盘,禁止U盘复制电脑文件、禁止电脑文件复制到U盘、禁止复制计算机文件到U盘的方法...