网易2017校园招聘笔试程序题(分田地)

  • Post author:
  • Post category:其他


题目描述:

牛牛和 15 个朋友来玩打土豪分田地的游戏,牛牛决定让你来分田地,地主的田地可以看成是一个矩形,每个位置有一个价值。分割田地的方法是横竖各切三刀,分成 16 份,作为领导干部,牛牛总是会选择其中总价值最小的一份田地, 作为牛牛最好的朋友,你希望牛牛取得的田地的价值和尽可能大,你知道这个值最大可以是多少吗?

输入描述:

每个输入包含 1 个测试用例。每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 75),表示田地的大小,接下来的 n 行,每行包含 m 个 0-9 之间的数字,表示每块位置的价值。

输出描述:

输出一行表示牛牛所能取得的最大的价值。

输入例子:

4 4

3332

3233

3332

2323

输出例子:

2

算法思路

我已开始想不出来很好的思路,然后瞄了一眼其他人的解答,看了一个找出最小的,然后合并行和列,直到最终结果是4行4列的思路,虽然我感觉这贪心不正确,然而我想到的穷举法时间复杂度太高,就把这个思路实现了一下,一如神坑似海,花费了我2小时40分钟debug+调试+运行+提交代码,结果还不是太。。。。

代码如下:

// FenTianDi.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;


struct Pos
{
    int i, j;
    Pos() :i(0), j(0) {}
    Pos(int a, int b) :i(a), j(b) {}
};

void print(int ** arr, int n, int m)
{
    cout << "\n***********************************\n";
    for (int i = 0;i < n;++i)
    {
        cout << endl;
        for (int j = 0;j < m;++j)
            cout << arr[i][j] << " ";
    }
    cout << "\n";
}

Pos arrMinPos(int ** arr, int n, int m)
{
    int min = arr[0][0];
    Pos minPos(0, 0);
    for (int i = 0;i < n;++i)
        for (int j = 0;j < m;++j)
        {
            if (arr[i][j] < min)
            {
                min = arr[i][j];
                minPos = Pos(i, j);
            }
        }
    return minPos;
}



int ** newarr(int n, int m)
{
    int ** arr = new int*[n];
    for (int i = 0;i < n;++i)arr[i] = new int[m];
    return arr;
}

void delarr(int ** arr, int n, int m)
{
    for (int i = 0;i < n;++i) 
    {
        delete arr[i]; 
        arr[i] = nullptr;
    }
    delete arr;
    arr = nullptr;
}


int main()
{
    ifstream fin("file01.txt");
    int m, n;
    fin >> n >> m;// n 行,每行包含 m 个
    int ** arr = new int*[n];
    char tmp;
    for (int i = 0;i < n;++i)arr[i] = new int[m];
    for (int i = 0;i < n;++i)
        for (int j = 0;j < m;++j)
        {
            fin >> tmp;
            arr[i][j] = tmp - '0';
        }


    if (n == 4 && m == 4)
    {
        Pos pmin = arrMinPos(arr, n, m);
        cout << arr[pmin.i][pmin.j] << endl;
        return 0;
    }
    else if (n <= 3 || m <= 3)cout << "\nError input !!!\n";

    int tn = n, tm = m;
    while (!(tn == 4 && tm == 4))
    {
        Pos pmin = arrMinPos(arr, tn, tm);
        int valmin = arr[pmin.i][pmin.j];
        int choose = -1;
        int ** narrUP = nullptr, ** narrDOWN = nullptr, ** narrLEFT = nullptr, ** narrRIGHT = nullptr;
        bool flag1 = false, flag2 = false, flag3 = false, flag4 = false;
        if (tn > 4)//和上下行合并;
        {
            if (pmin.i > 0)//和上一行合并,判断是不是第一行;
            {
                narrUP = newarr(tn - 1, tm);
                flag1 = true;

                for (int i = 0;i <= pmin.i - 2;++i)
                    for (int j = 0;j <= tm - 1;++j)
                        narrUP[i][j] = arr[i][j];

                for (int j = 0;j <= tm - 1;++j)
                    narrUP[pmin.i - 1][j] = arr[pmin.i - 1][j] + arr[pmin.i][j];

                for (int i = pmin.i;i <= tn - 2;++i)
                    for (int j = 0;j <= tm - 1;++j)
                        narrUP[i][j] = arr[i + 1][j];
            }
            if (pmin.i < tn - 1)//和下一行合并,判断是不是最后一行;
            {
                narrDOWN = newarr(tn - 1, tm);
                flag2 = true;

                for (int i = 0;i <= pmin.i - 1;++i)
                    for (int j = 0;j <= tm - 1;++j)
                        narrDOWN[i][j] = arr[i][j];

                for (int j = 0;j <= tm - 1;++j)
                    narrDOWN[pmin.i][j] = arr[pmin.i + 1][j] + arr[pmin.i][j];

                for (int i = pmin.i + 1;i <= tn - 2;++i)
                    for (int j = 0;j <= tm - 1;++j)
                        narrDOWN[i][j] = arr[i + 1][j];
            }
        }

        if (tm > 4)//和左右列合并;
        {
            if (pmin.j > 0)//和第一列合并,判断是不是第一;
            {
                narrLEFT = newarr(tn, tm - 1);
                flag3 = true;

                for (int i = 0;i <= tn - 1;++i)
                    for (int j = 0;j <= pmin.j - 2;++j)
                        narrLEFT[i][j] = arr[i][j];

                for (int i = 0;i <= tn - 1;++i)
                    narrLEFT[i][pmin.j - 1] = arr[i][pmin.j - 1] + arr[i][pmin.j];

                for (int i = 0;i <= tn - 1;++i)
                    for (int j = pmin.j;j <= tm - 2;++j)
                        narrLEFT[i][j] = arr[i][j + 1];
            }
            if (pmin.j < tm - 1)//和下一行合并,判断是不是最后一行;
            {
                narrRIGHT = newarr(tn, tm - 1);
                flag4 = true;

                for (int i = 0;i <= tn - 1;++i)
                    for (int j = 0;j <= pmin.j - 1;++j)
                        narrRIGHT[i][j] = arr[i][j];

                for (int i = 0;i <= tn - 1;++i)
                    narrRIGHT[i][pmin.j] = arr[i][pmin.j] + arr[i][pmin.j + 1];

                for (int i = 0;i <= tn - 1;++i)
                    for (int j = pmin.j + 1;j <= tm - 2;++j)
                        narrRIGHT[i][j] = arr[i][j + 1];
            }
        }

        int min1 = 800000, min2 = 800000, min3 = 800000, min4 = 800000;

        print(arr, tn, tm);//测试代码;

        if (flag1)
        {
            print(narrUP, tn - 1, tm);//测试代码;
            Pos p = arrMinPos(narrUP, tn - 1, tm);
            min1 = narrUP[p.i][p.j];
            if (valmin <= min1)choose = 1;
        }
        if (flag2)
        {
            print(narrDOWN, tn - 1, tm);
            Pos p = arrMinPos(narrDOWN, tn - 1, tm);
            min2 = narrDOWN[p.i][p.j];
            if (valmin <= min2)choose = 2;
        }
        if (flag3)
        {
            print(narrLEFT, tn, tm - 1);
            Pos p = arrMinPos(narrLEFT, tn, tm - 1);
            min3 = narrLEFT[p.i][p.j];
            if (valmin <= min3)choose = 3;
        }
        if (flag4)
        {
            print(narrRIGHT, tn, tm - 1);
            Pos p = arrMinPos(narrRIGHT, tn, tm - 1);
            min4 = narrRIGHT[p.i][p.j];
            if (valmin <= min4)choose = 4;
        }
        switch (choose)
        {
        case 1:
            delarr(arr, tn, tm);
            if(flag2)delarr(narrDOWN, tn - 1, tm);
            if (flag3)delarr(narrLEFT, tn, tm - 1);
            if (flag4)delarr(narrRIGHT, tn, tm - 1);
            arr = narrUP;
            --tn;
            break;
        case 2:
            delarr(arr, tn, tm);
            if (flag1)delarr(narrUP, tn - 1, tm);
            if (flag3)delarr(narrLEFT, tn, tm - 1);
            if (flag4)delarr(narrRIGHT, tn, tm - 1);
            arr = narrDOWN;
            --tn;
            break;

        case 3:
            delarr(arr, tn, tm);
            if (flag1)delarr(narrUP, tn - 1, tm);
            if (flag2)delarr(narrDOWN, tn - 1, tm);
            if (flag4)delarr(narrRIGHT, tn, tm - 1);
            arr = narrLEFT;
            --tm;
            break;
        case 4:
            delarr(arr, tn, tm);
            if (flag1)delarr(narrUP, tn - 1, tm);
            if (flag2)delarr(narrDOWN, tn - 1, tm);
            if (flag3)delarr(narrLEFT, tn, tm - 1);
            arr = narrRIGHT;
            --tm;
            break;
        }

    }
    Pos pmin = arrMinPos(arr, 4, 4);
    cout << arr[pmin.i][pmin.j] << endl;

    /*for (int i = 0;i < n;++i)
    {
        cout << endl;
        for (int j = 0;j < m;++j)
            cout << arr[i][j] << " ";
    }*/



    fin.close();
    return 0;
}



版权声明:本文为vonmax007原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。