牛客网答题笔记---地域划分

来源:互联网 发布:中标麒麟安装软件 编辑:程序博客网 时间:2024/05/16 12:14

题目描述

现在有一块长条形的土地,这个土地我们可以看成是由n块小方格连接而成的(这些小方格我们可以将之编号为1到n)
我们需要将其划分成两个部分,分别种上不同的作物(即作物A和B),划分必须在某两个小方格之间进行,或者在土地的最左端或最右端,若划分在第i块到第i+1块间进行,则划分后,第1至第i块地种A,剩下的地种B。
现在有一些专家对土地进行了检测,他们每个人评估了每块土地适合种的作物。请你找到一个合适的划分,使得其与所有专家的评估最吻合,也就是说,你划分到A而专家评估为B的次数和你划分到B而专家评估为A的次数之和最小

输入描述:

每组数据给定一个专家评估表land(其中0为评估A,1为评估B),以及小块数量n(1≤n≤300),专家评估次数m(1≤m≤300)

输出描述:

请返回你的划分,即i和i+1。若在最左端,则输出0,1;在最右端则输出n,n+1。若有多解输出最靠左的划分。

输入例子:

[[1,1,1,1],[0,0,0,0],[1,0,1,1]],4,3

输出例子:

[0,1]

题目分析

上面题目中的加粗部分是对题目的一个理解的要点:
1. 首先是:我们(是我们)来将n块小方格划分成两个部分(注意是两个部分,即A和B),之后是划分取一个i和i+1,规则是:在1~i之间的种A,剩下的种B
2. 之后是:有一些专家对土地进行检测(专家的检测),题目给出了一系列专家的检测,然后我们要去和这些检测结果比对

有了这些要点之后,我们再来分析题目的意思以及怎么转换成代码:

  1. 我们可以将土地分成n+1种类型,就拿题目中的例子你n = 4来说,这时候:

    这个第i块实际是下标i-1,i = 多少,表示第i块,这个0~i-1 表示第一块到第i块 i = -1:0~-1种A,剩下的种B :1 1 1 1i = 1 :0 ~ 0 种A,剩下的种B :0 1 1 1i = 2 :0 ~1 种 A ,剩下的种B:0 0 1 1i = 3 :0 ~ 2种 A ,剩下的种B:0 0 0 1 i = 4 :0 ~ 3种A,也就是全部种A(下标最大到3):0 0 0 0

2.有了这个之后,我们就可以开始比较了,得比较5次,求得里面和预估次数相差最少的那一次,或者说如果有多次,取最靠左边的划分。
开始比较:

1.对比第一次: 1 1 1 1      专家1: 1 1 1 1      专家2: 0 0 0 0        我选1,专家却选了0,这里+4      专家3: 1 0 1 1        同上,这里只有一个为0,这里+1得到结果为:52.对比第二次: 0 1 1 1      专家1: 1 1 1 1        我选0,专家选1,这里+1       专家2: 0 0 0 0        我选1,专家选0,这里+3      专家3: 1 0 1 1        我选0,专家选1,+1;我选1,专家选0,+1得到结果为:6.......之后的比较结果递推下去

3.仔细查看,我们之前的比较,从i=-1开始,比较的就是i的左边(包括i)为1的个数,和i的右边(不包括i)为0的个数(想想:我们的划分是从全1,一步步到全0的,也就是1111 -> 0111 -> 0011 -> 0001 -> 0000 ,也就是当前的那个划分[i,i+1]中的i左边的为1的数,和i右边为0的数

代码

那么这样就来看代码了:

class Partition {public:    vector<int> getPartition(const vector<vector<int> >& land, int n, int m) {        int min = INT_MAX;        int res = 0;        for(int i = -1;i < n;i++){            int count = 0;            //这里的j小于m是第几个专家,i别用来划分左右两边                 for(int j = 0;j < m;j++){                int left = i;                int right = i+1;                while(left >= 0){                    if(land[j][left] == 1)                        count++;                    left--;                }                while(right < n){                    if(land[j][right] == 0)                        count++;                    right++;                }            }            if(count < min){                min = count;                res = i;            }        }        vector<int> out(2);        out[0] = res+1;        out[1] = res+2;        return out;    }};

python代码:

# -*- coding:utf-8 -*-class Partition:    # land 二维list,每个项为专家给出的划分,例如[[1,1,1,1],[0,0,0,0],[1,0,1,1]]    # 请函数返回一个划分的list,例如 [0,1]    def getPartition(self, land, n, m):        count = 100000        point = 0        for i in range(n+1):            temp = 0            for j in range(m):                left = i - 1                right = i                while left >= 0:                    if land[j][left] == 1:                        temp += 1                    left -= 1                while right < n:                    if land[j][right] == 0:                        temp += 1                    right += 1            if temp < count:                point = i-1                count = temp        res = []        res.append(point+1)        res.append(point+2)        return res
0 0