题目一如下:
八卦阵相传是由诸葛亮创设的一种战斗队形和兵力部署,由八种阵势组成。
为了方便,采用矩阵来描述一个八卦阵,它由八个单阵组成,每个单阵由多个兵力区域组成形成一种阵势,
如下图所示,其中数字为一个兵力区域的士兵个数。假设单阵与单阵之间兵力区域不会相邻,且单阵中每个兵力区域至少存在一个相邻兵力区域(注:相邻是指在其左上,正上,右上,右方,右下,正下,左下,左方与其相邻),请用最快的速度计算出八个单阵中的兵力(士兵个数)的最大值和最小值。
已输入字数: 0 / 10000 运行
编译器版本 : gcc 4.8.4
请使用标准输入输出(stdin,stdout) ;请把所有程序写在一个文件里,勿使用已禁用图形、文件、网络、系统相关的头文件和操作,如sys / stat.h, unistd.h, curl / curl.h, process.h
时间限制 : 1S(C / C++以外的语言为: 3 S) 内存限制 : 128M(C / C++以外的语言为: 640 M)
输入 :
输入描述,例如:
第一行输入是八阵图的行数。
第二行输入是八阵图的列数。
后续行输入每个区域兵力。每一行的数据中间使用空格分开,当前一行输入完成后回车输入下一行数据。
输出 :
输出描述,例如:
输出八个单阵中兵力最大值和最小值。
输入范例 :
20
20
34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 30
0 23 10 5 5 0 0 0 5 5 5 5 5 0 0 0 30 0 40 0
0 9 0 0 5 0 0 0 4 4 4 4 4 0 0 0 0 30 0 0
0 8 7 7 0 5 0 0 3 3 3 3 0 0 0 0 7 0 9 0
0 9 0 0 5 0 5 0 0 12 12 0 0 0 0 10 0 0 0 9
0 0 0 0 5 0 0 5 0 12 12 0 0 5 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 12 12 0 0 5 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0
40 30 3 6 6 0 0 0 0 0 0 0 0 5 5 0 0 0 10 0
0 0 20 0 0 6 6 0 0 0 0 0 0 0 5 6 5 10 10 0
40 30 3 7 6 0 0 0 0 0 0 0 0 0 0 6 0 0 10 0
0 0 0 0 0 0 0 17 0 0 0 0 17 0 0 6 5 7 7 0
0 0 0 0 0 0 0 0 7 0 0 7 0 0 0 0 0 0 0 0
0 20 0 0 7 0 0 0 0 4 4 0 0 0 0 0 10 0 0 0
0 20 0 0 7 0 0 0 0 4 4 0 0 0 0 0 10 0 0 0
0 20 0 0 7 0 0 0 0 4 4 0 0 0 0 0 10 0 0 0
0 30 0 7 0 0 0 0 0 5 5 0 0 0 0 0 0 10 0 50
0 40 7 0 0 0 0 0 0 5 5 0 0 0 0 0 0 0 50 0
43 30 25 10 50 0 0 0 6 6 6 6 0 0 0 0 0 50 0 0
输出范例:
323
116
一开始被这么一大段解释文字给唬住了。仔细分析,发现就是DFS里面的洪流算法思想。选点–>流水–>再选点–>再流水。
下面是代码段,并且有注释:
#include "stdafx.h"
#include<iostream>
using namespace std;
//搞定收工
bool check(int rows, int cols, int row, int col, bool** visited ,int **power) {//洪流检查
if (row >= 0 && row<rows && col >= 0 && col<cols&&!visited[row][col]&&power[row][col])//注意边界条件检查的范围
{
return true;
}
return false;//这里的返回值忘了,要加上,要不然内存会报错,因为如果没有返回值的话,那么系统默认的返回值为true,那么后面的程序会一直运行下去
}
static int save_power[8] = { 0 };//用全局变量存储解
int direction[8][2] = { -1,-1,-1,0,-1,1,0,-1,0,1,1,-1,1,0,1,1 };//二维数组存储要判断的四个方向
void Backtracking(int part,int rows, int cols, int row, int col, bool** visited, int **power) {
//正常的处理操作
if (check(rows, cols, row, col, visited,power))//没被访问过,且兵力大于零
{
visited[row][col] = true; //置访问标记为true,表示已经访问过
save_power[part] += power[row][col];
for (int i = 0; i <=7; i++)
{
Backtracking(part, rows, cols, row+direction[i][0], col+direction[i][1], visited,power);
//是row+direction[i][0], col+direction[i][1],并不是direction[i][0],direction[i][1],一开始就写错了
}
}
}
void CombineSolution(int rows,int cols ,int **power,bool **visited,int result[2]) { //二维数组就相当于是传地址,所以不用传引用
int part = 0;//part在两层循环内初始化,不是在两层循环外初始化
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols;j++) {
if (power[i][j] != 0 && !visited[i][j])
{
Backtracking(part, rows, cols, i, j, visited, power); //这里 i,j是下一个连通区域的起始节点
part++;
}
}
}
//计算最大值,最小值
int max =-1;
int min =9999999;
for (size_t i = 0; i <8; i++)
{
/*printf("%d ",save_power[i]);*/
if (save_power[i]>max)
{
max = save_power[i];
}
if (save_power[i]<min)
{
min = save_power[i];
}
}
result[0] = max ;
result[1] = min;
}
int main()
{
int rows, cols;
cin >> rows;//用cin直接读入
cin >> cols;
int** power = new int*[rows];//开辟m行
bool** visited = new bool*[rows];//开辟m行
//初始化值
for (int i = 0; i <rows; i++)
{
power[i] = new int[cols];
visited[i] = new bool[cols];
}
//初始化值兵力图和访问标记位
for (int i = 0; i <rows; i++) //注意初始化动态数组的范围
for (int j = 0; j <cols; j++)
{
cin >> power[i][j];
visited[i][j] = false;
}
int result[2] = { 0,0 };
CombineSolution(rows, cols, power,visited, result);
printf("%d %d ",result[0],result[1]);
system("pause");
return 0;
}
通过这次笔试发现,自己还有很多需要思考的地方,对于递归和回溯法,我还需再做做功课,遇到问题具体分析,不要被唬住了,加油!