Red and Black
There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move on red tiles, he can move only on black tiles.
Write a program to count the number of black tiles which he can reach by repeating the moves described above.
Input
The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20.
There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.
'.' - a black tile
'#' - a red tile
'@' - a man on a black tile(appears exactly once in a data set)
Output
For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).
Sample Input
6 9
....#.
.....#
......
......
......
......
......
井@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
.
...@...
.
..#.#..
..#.#..
0 0
Sample Output
45
59
6
13
下面是分别用广度优先搜索和深度优先搜索的解决方案
//(图论(广搜))
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cstdio>
#include<queue>
#include<stack>
#include<set>
#include<vector>
using namespace std;
struct node{
int x,y;//结构体变量的横纵坐标
};
int n,m,ans;//输入字符图形行数和列数
char s[25][25];//字符型邻接矩阵
int dis[4][2] = {0,1,0,-1,1,0,-1,0};//移动 数组,2个数为一组,模拟横纵坐标变化的过程,如0,1表示横坐标不变,纵坐标加1,即向上移动
void bfs(int dx,int dy){
queue<node>q;
node start,next;
start.x = dx;
start.y = dy;
s[start.x][start.y] = '#';//先把起点位置设为'#'
q.push(start);//将该点入队
while(!q.empty()) {
start = q.front();//将队头元素赋值给start,以便后面搜索其相邻元素
q.pop();//队头元素出队
for(int i = 0; i < 4; i++){//遍历该点四个方位邻接点
next.x = start.x + dis[i][0];//进行横纵坐标变化模拟移动
next.y = start.y + dis[i][1];
if(s[next.x][next.y] == '#'|| next.x > n || next.x <1|| next.y > m ||next.y <1){//移动到尽头或者'#'处返回
// if(s[next.x][next.y] == '#'|| next.x > n || next.y > m){
continue;//跳过,不再执行后续递归
}
s[next.x][next.y] ='#';//访问过就标记为#
ans++;
q.push(next);
}
/*for(int dx = -1;dx <= 1;dx++){//可模拟8个方位的移动变化
for(int dy = -1;dy <= 1;dy++)
}*/
}
}
int main(){
while(cin >> m >> n,m||n){
int sx = 0,sy = 0;//起点的横纵坐标,统计.的数量的变量
ans = 1;//因为其本身也要算上
for(int i = 1; i <= n; i++){
scanf("%s",s[i] + 1);//此处一行字符 按照 一个字符串来存%s,本来是s[i],由于i从1开始,所以s[i]首地址也加1
for(int j = 1; j <= m; j++){
if(s[i][j] == '@'){//寻找起始点的位置(横纵坐标)
sx = i;
sy = j;
break;
}
}
}
bfs(sx,sy);//从起点开始深搜
cout << ans << endl;
}
return 0;
}
//(图论(深搜))
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cstdio>
#include<queue>
#include<stack>
#include<set>
#include<vector>
using namespace std;
int n,m;//输入字符图形行数和列数
char s[25][25];//字符型邻接矩阵
int sx,sy,ans;//起点的横纵坐标,统计.的数量的变量
int dis[4][2] = {0,1,0,-1,1,0,-1,0};//移动 数组,2个数为一组,模拟横纵坐标变化的过程,如0,1表示横坐标不变,纵坐标加1,即向上移动
void dfs(int x,int y){
if(s[x][y] =='.'){
ans++;
}
s[x][y] = '#';//找到.后 把.置为#
int xx,yy;
for(int i = 0; i < 4; i++){//遍历该点四个方位邻接点
xx = x + dis[i][0];//进行横纵坐标变化模拟移动
yy = y + dis[i][1];
if(s[xx][yy] == '#'|| xx > n || xx <1|| yy > m ||yy <1){//移动到尽头或者'#'处返回
continue;//不再执行dfs递归
}
dfs(xx,yy);//递归遍历所有点的四个方向的点
/*for(int dx = -1;dx <= 1;dx++){//可模拟8个方位的移动变化
for(int dy = -1;dy <= 1;dy++)
}*/
}
}
int main(){
while(cin >> m >> n,m||n){
// if(n==0&&m==0)
// break;
ans = 1;//因为其本身也要算上
for(int i = 1; i <= n; i++){
scanf("%s",s[i] + 1);//此处一行字符 按照 一个字符串来存%s,本来是s[i],由于i从1开始,所以s[i]首地址也加1
for(int j = 1; j <= m; j++){
if(s[i][j] == '@'){//寻找起始点的位置(横纵坐标)
sx = i;
sy = j;
break;
}
}
}
dfs(sx,sy);//从起点开始深搜
cout << ans << endl;
}
return 0;
}
另一种提前设置好移动数组的做法
//#include <iostream>
//#include <cstdio>
//using namespace std;
//int cnt,n,m;
//char map[30][30];
//int doto[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
//void df(int i,int j)
//{
// cnt++;
// map[i][j]='#';//每次搜索完毕就赋值为‘#’,避免重复累加
// //对于每一点,对其上下左右都进行搜索一遍
// for(int k=0;k<4;k++)
// {
// int x=i+doto[k][0];
// int y=j+doto[k][1];
// if(x<n&&y<m&&x>=0&&y>=0&&map[x][y]=='.')//如果是黑砖则继续对黑砖进行四周搜索
// df(x,y);
// }
// return ;
//
//}
//int main()
//{
// int fi;
// int fj;
// while(cin>>m>>n)
// {
// if(n==0&&m==0)
// break;
// int i;
// for(i=0;i<n;i++)
// {
// int j;
// for(j=0;j<m;j++)
// {
// cin>>map[i][j];
// if(map[i][j]=='@')//记录初始位置
// {
//
// fi=i;
// fj=j;
// }
// }
//
// }
// cnt=0;
// df(fi,fj);//从最初的位置进行搜索
// cout<<cnt<<endl;
// }
// return 0;
//}
最短路径
在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?
Input
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
Output
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
Sample Input
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0
Sample Output
3
2
下面分别用图的广度优先算法和floyed算法,以及kruskal(邻接矩阵)、kruskal(邻接表)来解决这一问题
//(floyd求最短路径(邻接矩阵))
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cstdio>
#include<queue>
#include<stack>
#include<set>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 105;
int a[maxn][maxn];//邻接矩阵
int n,m;
void floyd(){
int s = 1;//s可以定义为为任意一个点
for(int i = 1; i <= n; i++){//每个j和k经过i时都要判断,共有n个i(中间点)
for(int j = 1; j <= n; j++){
if(a[i][j] != INF){
for(int k = 1; k <= n; k++){
if(a[j][i] + a[i][k] < a[j][k]){//判断一下j经过0,1,2,3,4....n(i)后到k是否比j-k(直接)距离短
a[j][k] = a[j][i] + a[i][k];
}
}
}
}
}
printf("%d\n",a[s][n]);
}
int main(){
while(cin >> n >> m,m || n){
memset(a,INF,sizeof(a));
while(m--){
int x,y,z;
cin >> x >> y >> z;
a[x][y] = a[y][x] = z;
}
floyd();
}
return 0;
}
//(图论(广搜))
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cstdio>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#define maxn 105
#define INF 0x3f3f3f3f
using namespace std;
int a[maxn][maxn];//表示两点距离的邻接矩阵
bool vis[maxn];//判断是否被访问过
int dis[maxn];// 表示两点距离的数组(用作中间变量)
int n,m;//全局变量,dijkstra()函数中也要用到
void dijk(int x,int y){
for(int i = 1; i <= y; i++){//初始化dis,vis
dis[i] = a[x][i];//[1][1]到[1][n]
vis[i] = false;//所有点都初始化为未访问过
}
vis[x] = true;//把第一个值设为已访问
int p = 0;
for(int i = 1; i <= y; i++){//为了每次循环都使minn恢复为INF
int minn = INF;
for(int j = 1; j <= y; j++){
if(vis[j] == 0 && dis[j] < minn){
minn = dis[j];//找到最小的dis[],即1到1,1到2,1到3,1到4...中的最小路径
p = j;//把最小路径(1到某点)对应的点赋值给p
}
}
vis[p] = true;//把找到的点设为以访问
for(int j = 1; j <= y; j++){//判断经过p点到j点的距离 是否比 直接从1点到j点的距离短
if(vis[j] == 0 && dis[p] + a[p][j] < dis[j]){//满足条件就更新dis[j]
dis[j] = dis[p] + a[p][j];
}
}
}
}
int main(){
while(cin >> n >> m,m||n){
int x,y,z;
memset(a,INF,sizeof(a));//邻接矩阵数组初始化
while(m--){
cin >> x >> y >> z;
a[x][y] = a[y][x] = z;
}
dijk(1,n);
cout << dis[n] << endl;//输出1到最后一个点(此题为n)的额最短路径
}
return 0;
}
////(dijkstra求最短路径(邻接矩阵))
//#include<iostream>
//#include<algorithm>
//#include<string>
//#include<string.h>
//#include<cstdio>
//#include<queue>
//#include<stack>
//#include<set>
//#include<vector>
//#define maxn 105
//#define INF 0x3f3f3f3f
//using namespace std;
//int a[maxn][maxn];//表示两点距离的邻接矩阵
//bool vis[maxn];//判断是否被访问过
//int dis[maxn];// 表示两点距离的数组(用作中间变量)
//int n,m;//全局变量,dijkstra()函数中也要用到
//void dijk(int x,int y){
// for(int i = 1; i <= y; i++){//初始化dis,vis
// dis[i] = a[x][i];//[1][1]到[1][n]
// vis[i] = false;//所有点都初始化为未访问过
// }
// vis[x] = true;//把第一个值设为已访问
// int p;//中间变量,用做当前找到的最短路径对应的点
// for(int i = 1; i <= y; i++){//每次都会新增一点然后求最短路径,共y个点,循环y次
// int minn = INF;//每次循环都使minn恢复为INF
// for(int j = 1; j <= y; j++){//找到下一个点
// if(vis[j] == 0 && dis[j] < minn){
// minn = dis[j];//找到最小的dis[],即1到1,1到2,1到3,1到4...中的最小路径
// p = j;//把最小路径(1到某点)对应的点赋值给p
// }
// }
// vis[p] = true;//把找到的点设为以访问
// for(int j = 1; j <= y; j++){//判断经过p点到j点的距离 是否比 直接从1点到j点的距离短
// if(vis[j] == 0 && dis[p] + a[p][j] < dis[j]){//满足条件就更新dis[j]
// dis[j] = dis[p] + a[p][j];//计算加入p点后目前1到各点的最短路径
// }
// }
// }
//}
//int main(){
// while(cin >> n >> m,m||n){
// int x,y,z;
// memset(a,INF,sizeof(a));//邻接矩阵数组初始化
// while(m--){
// cin >> x >> y >> z;
// a[x][y] = a[y][x] = z;
// }
// dijk(1,n);//迪杰斯特拉求1-n的最短路径
// cout << dis[n] << endl;//输出1到最后一个点(此题为n)的额最短路径
// }
// return 0;
//}
//(邻接表))
//#include<iostream>
//#include<algorithm>
//#include<string>
//#include<string.h>
//#include<cstdio>
//#include<queue>
//#include<stack>
//#include<set>
//#include<vector>
//using namespace std;
//#define INF 0x3f3f3f3f
//int dis[105];
//bool vis[105];//访问标记数组
//int n,m;
//struct Edge{
// int cost;//权值
// int next;//下一个点
//};
//vector<Edge> edge[105];//定义一个vector数组,来建立整个图
//void dijk(){
// for(int i = 1; i <= n; i++){//距离和访问数组初始化
// vis[i] = false;
// dis[i] = -1;
// }
// int newx = 1;//newx表示当前访问的点,从第一个点开始
// vis[newx] = true; //设置为已访问
// dis[newx] = 0;//第一个点到本身为0
// for(int i = 1; i <= n; i++){////每次都会新增一点然后求最短路径,共y个点,循环y次
// for(int j = 0; j < edge[newx].size(); j++){//当前点在vector数组
// int newnext;
// newnext = edge[newx][j].next;//把当前点(x)对应的vector数组(edge[newx])中包含的第j个结构的权值和对应的next点赋值给变量存储
// int newcost;
// newcost = edge[newx][j].cost;
// if(vis[newnext]=true){
// continue;//如果当前位置已经访问过,不再进行下面操作
// }
// if(dis[newnext]== -1 || newcost + dis[newx] < dis[newnext]){//dis[newnext]== -1代表未被访问过 经过中间点到newnext点的距离 是否比 直接从1点到newnext点的距离短
// dis[newnext] = newcost + dis[newx];//满足就更新dis[newnext]
// }
// }
// int minn;
// minn = INF;
// for(int j = 1; j <= n; j++){//找到下一个放进来的点
// if(vis[j] || dis[j] == -1){//dis[j]== -1代表newx到j点仍然没有连通,那该点肯定加不进来,不用进行后续操作
// continue;//如果当前位置已经访问过,不再进行下面操作
// }
// if(dis[j] < minn){
// minn = dis[j];//找到最小的dis[],即1到1,1到2,1到3,1到4...中的最小路径
// newx = j;//把找到的点加进来
// }
// }
// vis[newx] = true;
// }
// printf("%d\n",dis[n]);
//}
//int main(){
//// while(scanf("%d %d",&n,&m) != EOF,m||n){
// while(scanf("%d %d",&n,&m) != EOF){
// if(m == 0 && n == 0){
// break;
// }
// for(int i = 0; i < n; i++){
// edge[i].clear();//vector是全局变量,每次循环需要清空
// }
// for(int i = 0; i < m; i++){//建图(邻接表相互(x - y或y - x)的权值一样)
// int x,y,z;
// scanf("%d %d %d",&x,&y,&z);
// Edge temp;//定义一个结构体中间量
// temp.cost = z;//为这个量赋相应的值
// temp.next = y;
// edge[x].push_back(temp);//把下一个点为y的结构封装在vector数组edge里
// temp.next = x;
// edge[y].push_back(temp);//把下一个点为x的结构封装在vector数组edge里
// }
// dijk();
// }
// return 0;
//}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。