阿里算法岗笔试附加题一(5月11日)

题目一如下:
  八卦阵相传是由诸葛亮创设的一种战斗队形和兵力部署,由八种阵势组成。
  为了方便,采用矩阵来描述一个八卦阵,它由八个单阵组成,每个单阵由多个兵力区域组成形成一种阵势,
  如下图所示,其中数字为一个兵力区域的士兵个数。假设单阵与单阵之间兵力区域不会相邻,且单阵中每个兵力区域至少存在一个相邻兵力区域(注:相邻是指在其左上,正上,右上,右方,右下,正下,左下,左方与其相邻),请用最快的速度计算出八个单阵中的兵力(士兵个数)的最大值和最小值。
八卦阵示意图
  已输入字数: 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;
}

  通过这次笔试发现,自己还有很多需要思考的地方,对于递归和回溯法,我还需再做做功课,遇到问题具体分析,不要被唬住了,加油!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值