图:
一、图的类别:有向图与无向图
二、图的概念:图由点和线组成,点之间的线,分有方向和无方向。
三、创建图,就是创建出节点和节点之间的线。
建边:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N=100000+10;
const int M=100+10;
vector<int>G[N];
//x->y
void way1(){
G[x].push_back(y); //加边方式
int sz=G[x].size(); //遍历方式
for(int i=0;i<sz;i++){
int to=G[x][i];
}
}
//链式前向星
int tot,ver[N<<1],Next[N<<1],head[N];
//tot标号,ver[]存储每个编号的边连出去的点,Next[]往前连接的边的编号,head[]最后一个编号的边
void add(int u,int v){ //添加一条从u->v的边
++tot;ver[tot]=v;
Next[tot]=head[u];head[u]=tot;
}
void way2(){
add(x,y); //加边方式
for(int i=head[x];i;i=Next[i]){ //遍历方式
int to=ver[i];
}
}
int main(){
memset(head,0,sizeof head);
}
bfs—广度优先搜索
找v0到v6一条最短的路
①.搜索v0 ②.搜索v1,v2,v3 ③.搜索到v6
例题:
通过一年学习在杭州,宜芬飞终于到达家乡宁波。离开宁波一年,叶芬飞有很多人要见面。尤其是好朋友梅塞基
益芬飞的家在农村,但梅塞基的家在市中心。因此,伊芬菲与美世基安排在肯德基见面。宁波有很多肯德基,他们想选一个让总时间到它最小的。
现在给你一张宁波地图,伊芬菲和美世基都可以上下移动,向左移动,右移到相邻的公路上,花费11分钟。
输入
输入包含多个测试用例。
每个测试用例包括,前两个整数 n,m. (2<\n,m<=200)。
下 n 行,每行包含 m 字符。
‘Y’ 表示伊芬飞初始位置。
“M” 表示默塞基的初始位置。
“#” 禁止道路;
". "道路。
‘@’ Kcf
输出
对于每个测试用例输出的最小总时间,伊芬菲和美世基到达肯德基之一。你可能肯定总是有一个肯德基, 可以让他们见面。
示例输入
4 4
Y.#@
…
.#…
@…M
4 4
Y.#@
…
.#…
@#.M
5 5
Y…@.
.#…
.#…
@…M.
#…#
示例输出
66
88
66
代码:
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
//(x,y) pii Point=make_pair(x,y)
//获取x x=Point.first;
//获取y y=Point.second;
const int N=200+10;
const int M=10;
const int inf=0x3f3f3f3f; //无穷大
char s[N][N];
int sx[M],sy[M];
int n,m,dis[M][N][N];
int dx[M]={0,0,1,-1};
int dy[M]={1,-1,0,0};
void bfs(int id){
queue<pii>q; //先进先出
q.push(make_pair(sx[id],sy[id]));
dis[id][sx[id]][sy[id]]=0;
while(!q.empty()){
int x=q.front().first,y=q.front().second;
q.pop(); //记得
for(int i=0;i<4;i++){
int xx=x+dx[i],yy=y+dy[i]; //下一步要走的点
if(1<=xx && xx<= n && 1<=yy && yy<=m && dis[id][xx][yy]==inf && s[xx][yy]!='#'){
dis[id][xx][yy]=dis[id][x][y]+1;
q.push(make_pair(xx,yy));
}
}
}
}
int main(){
while(scanf("%d %d",&n,&m)!=EOF){
memset(dis,inf,sizeof dis);
for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
if(s[i][j]=='Y')sx[0]=i,sy[0]=j;
if(s[i][j]=='M')sx[1]=i,sy[1]=j;
}
bfs(0),bfs(1);
int res=inf;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(s[i][j]=='@'){
res=min(res,dis[0][i][j]+dis[1][i][j]);
}
printf("%d\n",res*11);
}
}
dfs—深度优先搜索
找v0到v6一条路(无需最短)
①V0->V1->V4,此时到底尽头,仍然到不了V6,原路返回到V1去搜索其他路径
②V0->V1->V2->V6,,找到目标节点,返回有解
例题:
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
输入
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
输出
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
示例输入
1
8
5
0
示例输出
1
92
10
代码:
#include<bits/stdc++.h>
using namespace std;
const int N =10+10;
int f[N],vis[N],n,cnt; //vis[i] 代表第i列之前已经被第vis[i]行放置
bool check(int row,int col){ //判断第row行第col列能不能放置棋子
if(vis[col])return false;
for(int i=1;i<=n;i++){ //45°
if(vis[i] && abs(i-col)==abs(vis[i]-row))return false;
}
return true;
}
void dfs(int now){ //当前准备放置第now行
if(now==n+1){ //是否对答案有贡献
cnt++;
return;
}
for(int i=1;i<=n;i++){
if(check(now,i)){
vis[i]=now; //第i列已经由第now行放置
dfs(now+1); //放置下一行
vis[i]=0; //还原
}
}
}
int main(){
for(n=1;n<=10;n++){
memset(vis,0,sizeof vis);
cnt=0;
dfs(1);
f[n]=cnt;
}
int x;while(scanf("%d",&x)!=EOF){
if(x==0)break;
printf("%d\n",f[x]);
}
}