以下是广搜水题
题意:输入一个n*n的迷宫,输入从起点到终点的最短路
输入:
12 //迷宫大小
2 9 11 8 //起点和终点
1 1 1 1 1 1 1 1 1 1 1 1 //邻接矩阵,0表示通,1表示不通
1 0 0 0 0 0 0 1 0 1 1 1
1 0 1 0 1 1 0 0 0 0 0 1
1 0 1 0 1 1 0 1 1 1 0 1
1 0 1 0 0 0 0 0 1 0 0 1
1 0 1 0 1 1 1 1 1 1 1 1
1 0 0 0 1 0 1 0 0 0 0 1
1 0 1 1 1 0 0 0 1 1 1 1
1 0 0 0 0 0 1 0 0 0 0 1
1 1 1 0 1 1 1 1 0 1 0 1
1 1 1 1 1 1 1 0 0 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
输出:
(2,9)->(3,9)->(3,8)->(3,7)->(4,7)->(5,7)->(5,6)->(5,5)->(5,4)->(6,4)->(7,4)->(7,3)->(7,2)->(8,2)->(9,2)->(9,3)->(9,4)->(9,5)->(9,6)->(8,6)->(8,7)->(8,8)->(9,8)->(9,9)->(10,9)->(11,9)->(11,8)
27
代码:
#include<cstdio>
using namespace std;
int dwax[4]={0,0,1,-1},dway[4]={1,-1,0,0};
int n,m,state[2501][2],father[2501],px,py,x,y,head,tail,s;
bool a[51][51];
void write(int x,int dep)
{
if (x==0) return;//如果到x则0则为返回完毕
s++;
write(father[x],dep+1);//返回
printf("(%d,%d)",state[x][0],state[x][1]);//输出路径
if (dep!=0) printf("->");
}
void bfs()
{
head=0;//预处理
tail=1;
do
{
head+=1;//出队
x=state[head][0];
y=state[head][1];
for (int i=0;i<4;i++) if (!a[x+dwax[i]][y+dway[i]] && x+dwax[i]<=n && y+dway[i]<=n && x+dwax[i]>=1 && y+dway[i]>=1)//判断是否可以通行{tail++;//入队father[tail]=head;state[tail][0]=x+dwax[i];state[tail][1]=y+dway[i];a[x+dwax[i]][y+dway[i]]=true;//封路if (x+dwax[i]==px && y+dway[i]==py)//判断终点{write(tail,0);return;}} }while (head<tail);//如果队列空了则退出}
int main()
{scanf("%d%d%d%d%d",&n,&x,&y,&px,&py);int q=0;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++){scanf("%d",&q);if (q==1) a[i][j]=true;}//以上为输入不解释state[1][0]=x;state[1][1]=y;a[x][y]=true;bfs();printf("\n%d",s);
}
题目2:骑士旅行
在一个n m 格子的棋盘上,有一只国际象棋的骑士在棋盘的左下角 (1;1)(如图1),骑士只能根据象棋的规则进行移动,要么横向跳动一格纵向跳动两格,要么纵向跳动一格横向跳动两格。 例如, n=4,m=3 时,若骑士在格子(2;1) (如图2), 则骑士只能移入下面格子:(1;3),(3;3) 或 (4;2);对于给定正整数n,m,I,j值 (m,n<=50,I<=n,j<=m) ,你要测算出从初始位置(1;1) 到格子(i;j)最少需要多少次移动。如果不可能到达目标位置,则输出"NEVER"。
输入:
5 3
1 2
输出:
3
代码:
#include<cstdio>
using namespace std;
int dwax[8]={1,1,-1,-1,2,2,-2,-2},dway[8]={2,-2,2,-2,1,-1,1,-1};
int n,m,state[2501][3],father[2501],px,py,x,y,head,tail,s;
bool a[51][51];
void write(int x)//检测bug的攻击
{if (x==0) return;s++;write(father[x]);printf("[%d , %d]->[%d , %d]\n",state[father[x]][0],state[father[x]][1],state[x][0],state[x][1]);//输出路径
}
void bfs()
{head=0;//初始化不解释tail=1;do{head+=1;//出队x=state[head][0];y=state[head][1];for (int i=0;i<8;i++) if (!a[x+dwax[i]][y+dway[i]] && x+dwax[i]<=n && y+dway[i]<=m && x+dwax[i]>=1 && y+dway[i]>=1)//判断可否通行{tail++;father[tail]=head;state[tail][0]=x+dwax[i];state[tail][1]=y+dway[i];state[tail][2]=state[head][2]+1;a[x+dwax[i]][y+dway[i]]=true;//封路if (x+dwax[i]==px && y+dway[i]==py){//write(tail);s=state[tail][2];return;}} }while (head<tail);//空队列结束广搜
}
int main()
{scanf("%d%d%d%d",&m,&n,&px,&py);state[1][0]=1;state[1][1]=1;state[1][2]=1;a[1][1]=true;//输入初始化不解释bfs();if (head==tail) printf("NEVER");else printf("%d",s-1);//输出不解释
}
题目3:翻币问题
有N个硬币(6<=N<=20000)全部正面朝上排成一排,每次将其中5个硬币翻过来放在原位置,直到最后全部硬币翻成反面朝上为止。试编程找出步数最少的翻法,输出最少步数及翻法。
输入:
6
输出:
6
代码:
#include<cstdio>
using namespace std;
int state[20001],father[20001],head,tail,s,n;
bool ok[20001];
void print(int x)//返回输出
{if (x==0) return;print(father[x]);//printf("%d:%d\n",s,state[x]);s++;
}
void bfs()
{state[1]=n;head=0;tail=1;do{head++;//出队for (int i=0;i<=5;i++)//翻得硬币正面个数if (state[head]>=i && n-state[head]>=5-i)//如果正面和反面数量足够{tail++;//入队father[tail]=head;//记录父节点state[tail]=state[head]-i+5-i;//翻if (ok[state[tail]])//判断有没有重复{tail--;continue;}ok[state[tail]]=true;//封if (state[tail]==0)//判断结束{print(tail);return;}}}while (head<tail);//结束队列
}
int main()
{scanf("%d",&n);bfs();printf("%d",s-1);//输出
}
题目4:最优乘车
H城是一个旅游胜地,每年都有成千上万的人前来观光。为方便游客,巴士公司在各个旅游景点及宾馆,饭店等地都设置了巴士站并开通了一些单程巴上线路。每条单程巴士线路从某个巴士站出发,依次途经若干个巴士站,最终到达终点巴士站。
一名旅客最近到H城旅游,他很想去S公园游玩,但如果从他所在的饭店没有一路已士可以直接到达S公园,则他可能要先乘某一路巴士坐几站,再下来换乘同一站台的另一路巴士, 这样换乘几次后到达S公园。
现在用整数1,2,…N 给H城的所有的巴士站编号,约定这名旅客所在饭店的巴士站编号为1…S公园巴士站的编号为N。
写一个程序,帮助这名旅客寻找一个最优乘车方案,使他在从饭店乘车到S公园的过程中换车的次数最少。
题目很烦是吧!
输入:
3 7
6 7
4 7 3 6
2 1 3 5
输出:
2
代码:
#include<cstdio>
using namespace std;
int a,k,bus[101][101],num[101][101],state[10001][3],head,tail,s,n,m;
char c;
bool ok[101];
void bfs()
{head=0;tail=1;state[1][0]=0;state[1][1]=1;state[1][2]=0;//初始化不解释do{head++;for (int i=1;i<=num[state[head][1]][0];i++)//枚举当前站可以到达的站{if (ok[num[state[head][1]][i]]) continue;//去重ok[num[state[head][1]][i]]=true;//封tail++;state[tail][1]=num[state[head][1]][i];state[tail][0]=state[head][0]+1;//状态读入if (state[tail][1]==n)//判断结束{s=state[tail][0];return;}}}while(head<=tail);
}
int main()
{scanf("%d%d",&m,&n);scanf("\n");for (int i=1;i<=m;i++){while ((c=getchar())!='\n'){if (c!=' ') a=a*10+c-48;//读取数字else {k++;bus[i][k]=a;//记录该公交线for (int j=1;j<k;j++) {num[bus[i][j]][0]++;num[bus[i][j]][num[bus[i][j]][0]]=a;//记录该点可以到达哪站}a=0;}}k++;bus[i][k]=a;for (int j=1;j<k;j++) {num[bus[i][j]][0]++;num[bus[i][j]][num[bus[i][j]][0]]=a;}//最后一个的处理a=0;bus[i][0]=k;k=0;}//以上为预处理bfs();if (s==0) printf("NO");else printf("%d",s-1);
}
好了,初见题就那么多。