首页 > 试题广场 >

地域划分

[编程题]地域划分
  • 热度指数:1042 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

现在有一块长条形的土地,这个土地我们可以看成是由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,1],[0,0,0,0],[1,0,1,1]],4,3

输出

[0,1]
import java.util.Scanner;


public class PartitionLand {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner = new Scanner(System.in);
		while (scanner.hasNext()) {
			int n = scanner.nextInt();
			int m = scanner.nextInt();
			int[][] land = new int[m][n];
			for (int i = 0; i < m; i++) {
				for (int j = 0; j < n; j++) {
					land[i][j] = scanner.nextInt();
				}
			}
			System.out.println(getPartition(land, n, m)[0]);
			System.out.println(getPartition(land, n, m)[1]);
		}
	}

	public static int[] getPartition(int[][] land, int n, int m) {
		int minMisFit = Integer.MAX_VALUE;
		int index = -1; // 用来保存划分位置的临时变量
		int[] result = new int[2];// 返回的结果
		int[] par = new int[n];
		for (int i = 0; i <= n; i++) { // 遍历划分位置
			// 构造划分
			for (int j = 0; j < i; j++) {
				par[j] = 0;
			}
			for (int j = i; j < n; j++) {
				par[j] = 1;
			}
			// 和各个专家的划分进行对比
			int diffNum = 0;
			for (int k = 0; k < m; k++) {
				diffNum += numOfMisFit(par, land[k]);
			}
			if (diffNum < minMisFit) {
				minMisFit = diffNum;
				index = i;
			}
		}
		result[0] = index;
		result[1] = index + 1;
		return result;
	}
	//两个划分的不一致统计
	public static int numOfMisFit(int[] par1, int[] par2) {
		int num = 0;
		for (int i = 0; i < par1.length; i++) {
			if (par1[i] != par2[i]) {
				num++;
			}
		}
		return num;
	}
}


编辑于 2016-09-29 10:04:34 回复(0)
更多回答
public class Partition {
    public int[] getPartition(int[][] land, int n, int m) {
        // write code here
        int count,bestPos = 0,bestVal = Integer.MAX_VALUE;
        for (int position = -1;position < n;position++){
            count = 0;
            for (int i = 0; i < m; i++) {
                for (int j = 0; j <= position; j++)
                    if (land[i][j]!=0)
                        count++;
                for (int j = position+1; j < n; j++)
                    if (land[i][j]!=1)
                        count++;
            }
            if (count<bestVal){
                bestVal = count;
                bestPos = position+1;
            }
        }
        return new int[]{bestPos,bestPos+1};
    }
}
编辑于 2016-04-19 22:15:58 回复(1)
import java.util.*;

public class Partition {
    public int[] getPartition(int[][] land, int n, int m) {
        // write code here
        
    	if(land==null)
    		return null;
    	int[][] left=new int[m][n+1];
    	int[][] right=new int[m][n+1];
    	for(int i=0;i<m;++i)
    	{
    		left[i][0]=0;
    		right[i][n]=0;
    	}
    	for(int i=0;i<m;++i)
    		for(int j=1,k=n-1;j<=n&&k>=0;++j,--k)
    		{
    			if((land[i][j-1]&1)==1)//说明划分错误
    				left[i][j]=left[i][j-1]+1;
    			else
    				left[i][j]=left[i][j-1];
    			if((land[i][k]&1)==0)//也说明划分错误
    				right[i][k]=right[i][k+1]+1;
    			else
    				right[i][k]=right[i][k+1];
    		}
    	int index=0;
    	int min=Integer.MAX_VALUE;
    	for(int j=0;j<n+1;++j)
    	{
    		int cursum=0;
    		for(int i=0;i<m;++i)
    		{
    			cursum+=left[i][j]+right[i][j];
    		}
    		if(cursum<min)
    		{
    			min=cursum;
    			index=j;
    		}
    	}
    	int[] ans=new int[2];
    	ans[0]=index;
    	ans[1]=index+1;
    	return ans;
    
    }
}
DP,空间换时间,left[i][j]表示第i+1次评估的时候在第j个位置上划分
(包括j,也就是位置j的右边)的得到的错误次数,那么当land[i][j]=1的时候表示
划分错误,left[i][j]=left[i][j-1],否则,left[i][j]=left[i][j-1],right
原理一样,注意j的取值范围为0~n。
	

编辑于 2016-06-14 14:07:44 回复(1)
//我们需要找到对没块地的所有专家的判定结果的一个汇总值
vector<int> getPartition(const vector<vector<int> >& land, int n, int m)
{
      vector<int>result;
      if(m<=0 || n<=0)
          return result;
      vector<int> n_isRight(n);  //保存每块地的值,后续计算时,0 就-1,1就+1
      for(int i=0;i<n;i++)
          n_isRight.push_back(0);
      int aa=n_isRight.size();

      for(int j=0;j<n;j++)
      {
         for(int i=0;i<m;i++)
         {
             if(land[i][j]==1)
                 n_isRight[j]++;
              if(land[i][j]==0)
                 n_isRight[j]--;
         }
      }

      vector<int>land_local(n+1);  //保存n+1个位置的 最大的专家判定的结果
        for(int i=0;i<n+1;i++) //n+1
          land_local.push_back(0);
       
        for(int i=0;i<=n;i++)//n+1
        {
            int max=0;
           for(int j=0;j<i;j++)
           {
                  if(n_isRight[j]<0)
                      max++;
                  else if(n_isRight[j]>0)
                      max--;
                  else{}
           }
            for(int j=i;j<n;j++)
           {
                  if(n_isRight[j]<0)
                      max--;
                  else if(n_isRight[j]>0)
                      max++;
                  else{}
           }
            land_local[i]=max;
        }
        int max=0;
        int p=0;
        for(int i=n;i>=0;i--)
        {
           if(land_local[i]>=max)
             { 
                 max=land_local[i];    //找到最大结果,就是最小的错误结果
                 p=i;
           }
        }
        result.push_back(p);
        result.push_back(p+1);
        return result;
}
发表于 2016-08-24 17:22:55 回复(0)
//一开始没看懂题意,尴尬==
int min = Integer.MAX_VALUE;
        int position = -1;
        //int count = 0;
        int bestPosition = 0;
        
        for(;position < n;position++){
            int count = 0;
            for(int i = 0;i < m;i++){
                for(int j = 0;j <= position;j++){
                    if(land[i][j] == 1){
                        count++;
                    }
                }
                for(int j = position + 1;j < n;j++){
                    if(land[i][j] == 0){
                        count++;
                    }
                }
            }
            if(min > count){
                min = count;
                bestPosition = position+1;
            }
            
        }
        return new int[]{bestPosition,bestPosition+1};

发表于 2017-12-23 16:17:44 回复(0)
class Partition {
public:
    vector<int> getPartition(const vector<vector<int> >& land, int n, int m) {       
        int n0=0;
        int i,j;
        //统计所有0的个数为n0。
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(land[j][i]==0)
                    n0++;               
            }
        }
        int min=n0;
        int num0=n0;
        int num1=0;
        vector<int>out(2);
        out[0]=0;out[1]=1;
        //从最左边开始,初始化误差就是刚才的n0的值。
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)     
            {
                if(land[j][i]==0)  
                {
                    num0--;    
                }
                else
                {
                    num1++;
                }
            }
            if((num0+num1)<min)
            {                
                min=num0+num1;
                out[0]=i+1;
                out[1]=i+2;               
            }
        }
        return out;
    }
};
发表于 2017-05-15 20:49:51 回复(0)
异或的思路
发表于 2017-04-24 11:40:12 回复(0)

class Partition {
public:
    vector<int> getPartition(const vector<vector<int> >& land, int n, int m) {
       int left[n+1];
                 memset(left,0,sizeof(left));
                 int sum = 0;
                for(int i=1;i<=m;i++){
    
                   for(int j=1;j<=n;j++){
                        left[j]+=land[i-1][j-1];
                        sum+=land[i-1][j-1];
                }
    
            }
        for(int i=1;i<=n;i++){
                left[i]+=left[i-1];
                
            }
            int min = 100000;
            int ans = 0;
            for(int i=0;i<=n;i++){
                if(min > left[i]+((n-i)*m-(sum-left[i]))){
                    min = left[i]+((n-i)*m-(sum-left[i]));
                    ans = i;
                }
            }         
            vector<int>a;
            a.push_back(ans);
            a.push_back(ans+1);
            return a;

    }
};
发表于 2016-12-28 16:18:18 回复(0)
/**
 * 对@欠扁的小篮子的代码思路进行解释了,但是还是有没看懂的地方,pos为什么要从-1开始而不是从0,
 * 还有为什么bestPos = position + 1;而不是bestPos = position
 */
public class Partition{
	/**
	 * @param land 二维数组
	 * @param n 列数
	 * @param m 行数
	 * @return
	 */
	public int[] getPartition(int[][] land, int n, int m) {
		int count = 0;// 划分到A而专家评估为B的次数和你划分到B而专家评估为A的次数
		int bestPos = 0;// 划分的位置
		int bestVal = Integer.MAX_VALUE;// 次数之和的最小值
		for (int position = -1; position < n; position++) {
			count = 0;
			for (int i = 0; i < m; i++) {//单独对每一行进行判断
				for (int j = 0; j <= position; j++)//0-position种A
					if (land[i][j] != 0)//如果说不是A
						count++;
				for (int j = position + 1; j < n; j++)//position+1-n种B
					if (land[i][j] != 1)
						count++;
			}
			if (count < bestVal) {
				bestVal = count;
				bestPos = position + 1;//因为最开始元素是1
			}
		}
		return new int[] { bestPos, bestPos + 1 };
	}
}

发表于 2016-09-09 15:11:33 回复(0)
// 观察规律型
// 递推公式
vector<int> getPartition(const vector<vector<int> >& land, int n, int m) {
    vector<int> voteA(n);
    int sumA = 0;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j) {
            sumA += 1 - land[j][i];
            voteA[i] += 1 - land[j][i];
        }

    // 不同划分方案
    vector<int> cost(n + 1);
    for (int i = 0; i <= n; ++i)
        if (i == 0) cost[i] = sumA;
        else cost[i] = cost[i - 1] +  m - 2 * voteA[i - 1];
    int max_index = min_element(cost.begin(), cost.end()) - cost.begin();
    vector<int> result;
    result.push_back(max_index);
    result.push_back(max_index + 1);

    return result;
}

发表于 2016-08-31 09:38:51 回复(0)
classPartition {
public:
    vector<int> getPartition(constvector<vector<int> >& land, intn, intm) {
        // write code here
        vector<int> res(2);
        vector<int> eva(n,0);
        for(inti=0;i<n;i++){
        if(i>0) eva[i] += eva[i-1];
         for(intj=0;j<m;j++)// 计算到i的所有评估为B的个数
                eva[i] +=land[j][i];
        }
            
        intcurMin = 1e9;
        for(inti=0;i<=n;i++){
                int countA = 0,countB = 0;
                if(i>0) countB = eva[i-1];
                if(i<n) countA = (n-i)*m-(eva[n-1]-countB);
                if(countA+countB<curMin){
                    res[0] = i;
                    res[1] = i+1;
                    curMin = countA +countB;
                }
 
        }
        return res;
 
    }
};

编辑于 2016-08-23 00:01:15 回复(0)
class Partition {
public:
    vector<int> getPartition(const vector<vector<int> >& land, int n, int m) {
        // write code here
        vector<int> dp(n);//当前以j为划分时的错误数
        int index;
        dp[0] =0;//初始化为0
        index =0;
        for(int i=0; i<m; i++) {
            for( int j=0;j<n;j++) {
                if( land[i][j] == 0 ) {
                    dp[0]++; //以最左边为划分时评估为0时错误加1
                }
            }
        }
        for(int i=0; i<m; i++) {
            for( int j=0;j<n;j++) {
                if( land[i][j] == 0 ) {
                   dp[j] = dp[j-1]-1;//当前数为0时向右划分时则总错误数减1  
                }
                else {
                   dp[j] = dp[j-1]+1;
                }
            }
        }
        int min =500;
        for( int i=0;i<n;i++ ) {
            if( dp[i] < min ) {
                min = dp[i];
                index =i;
            }
        }
        vector<int> rs(2);
        rs[0] = index;
        rs[1] = index+1;
        return rs;
    }
};

编译通过,case测试不通过。哪位大牛帮我看下这代码错在哪里?
发表于 2016-08-05 15:28:06 回复(0)
public class Partition {
    public int[] getPartition(int[][] land, int n, int m) {
       
HashMap<Integer, Integer> hm = new HashMap<>();
int[] array = new int[n];
int t=0;
int d=n;
   LinkedList<Integer> lk = new LinkedList<>();
int [] array1 = new int[n+1];
for(int i=0;i<=n;i++){
for(int j=0;j<i;j++)
{
array[j]=1;
}
for(int b=0;b<m;b++)
for(int c=0;c<n;c++){
if(land[b][c]==array[c]){
t++;
}
}
hm.put(d, t);
d--;
t=0;
}
for(int q=0;q<=n;q++)
{
array1[q]=hm.get(q);
}
Arrays.sort(array1);
for(int x=n;x>=0;x--){
//System.out.println(x);
if(hm.get(x)==array1[0]){
lk.add(x);
}
}
        return new int [] {n-lk.getFirst(),n-lk.getFirst()+1};
    }
}
用了一个很傻的方法,有什么方法简化我的代码吗
发表于 2016-05-16 19:20:54 回复(0)
# -*- 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):
        # write code here
        # return [0, 1]
        
        index = 0
        min = 500
        for i in range(n + 1):
            sum = 0
            for j in range(0, m):
                sum += self.compare_block(land[j], i)
            if sum < min:
                index = i
                min = sum
        res = []
        res.append(index)
        res.append(index+1)
        return res

    def compare_block(self, block, sp):
        sum = 0
        ll = len(block)
        for i in range(sp):
            if block[i] == 1:
                sum += 1
        for i in range(sp, ll):
            if block[i] == 0:
                sum += 1
        return sum

发表于 2016-04-25 20:18:56 回复(0)
class Partition {
public:
    vector<int> getPartition(const vector<vector<int> >& la, int n, int m) {
       vector<vector<int> > land=la;
        vector <int> s1(m);
        vector<int>s2(m);
      
        for(int i=0;i<m;i++){
           for(int j=0;j<n;j++){
               if(land[i][j]==1)
                   s1[i]++;
               if(land[i][j]==0)
                   s2[i]++;
           }
       }
        vector<int> v1(m);
        v1[0]=s1[0];
        for(int i=1;i<m;i++){
            v1[i]=v1[i-1]+s1[i];
           
        }
         vector<int> v2(m);
        v2[m-1]=s2[m-1];
        for(int i=m-2;i>=0;i--){
            v2[i]=v2[i+1]+s2[i];
           
        }
        int min=10000; 
        int index=0;
        for(int i=0;i<m;i++){
            v1[i]+=v2[i];
            if(min>v1[i]){
                min=v1[i];
                index=i;
            }
        }
        return {index ,index+1};
    }
};
哪里错了呢???救助 !


发表于 2016-04-21 15:11:02 回复(0)
主要是找出自己所有的分割的可能性,分别和所有的专家异或,取异或结果最小值。我觉得我这种方法最容易理解了,笔试的时候不给测试用例太坑爹!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
import java.util.*;

public class Partition {
    public int[] getPartition(int[][] land, int n, int m) {
        // write code here
        //n是小块的数量,m是专家评估的次数
        int rr = getResult(land,initMyPartition(n,0),n,m);
        int flag = 0;
        
        for(int i = 1; i <= n; i++){
            int ee = getResult(land,initMyPartition(n,i),n,m);
            if(ee < rr){
                flag = i;
                rr = ee;
            }
            
        }
        int[] tt = new int[2];
        tt[0] = flag;
        tt[1] = flag + 1;
        // return initMyPartition(n,flag);
        return tt;
    }
   
    //m是有几行,n是有几列
    public int getResult(int[][] land, int[] my, int n, int m){
        
        int[][] result = new int[m][n];
        
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                result[i][j] = my[j]^land[i][j];
            }
        }
        
        return getSum(result, n, m);
        
    }
    
    //m是行,n是列,m在前,n在后,int[m][n],现遍历行,再遍历列
    public int getSum(int[][] ff, int n, int m){
        int flag = 0;
        for(int j = 0; j < m; j++){
            for(int i = 0; i < n; i++){
                flag += ff[j][i];
            }
        }
        return flag;
    }
    
    public int[] initMyPartition(int n, int k){        
        
        int[] res = new int[n];
        if(k > n + 1){
            return null;
        }
        else{
            //for循环是先判断再执行的!!!!!!!!!!!!!!
            for(int i = 0; i < k; i++){
                res[i] = 0;
            }
            
            for(int j = k; j < n; j++){
                res[j] = 1;
            }
        }
        return res;
    }
        
}

编辑于 2016-04-21 13:01:20 回复(1)
class Partition {
public:
    vector<int> getPartition(const vector<vector<int> >& land, int n, int m) {
        // write code here
        vector<int> v;
        int cnt[n+5];
        int min, ind;
        memset(cnt, 0, sizeof cnt);
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(land[i][j]){		//1
                    cnt[j+1]++;
                }
                else{				//0
                	cnt[0]++;
                  	cnt[j+1]--;
                }
            }
        }
        min = cnt[0];	ind = 0;
        for(int i = 1; i <= n; i++){
            cnt[i] += cnt[i-1];
            if(cnt[i] < min){
                min = cnt[i];
                ind = i;
            }
        }
        v.push_back(ind);	v.push_back(ind + 1);
        return v;
    }
};

发表于 2016-04-20 16:11:16 回复(0)
classPartition {
public:
    vector<int> getPartition(constvector<vector<int> >& land, intn, intm) {
      // write code here
    vector<int> vec;
    inti = 0;
    while(i < n){
        vec.push_back(1);
        i++;
    }
 
    intpos = 0;
    intmin = Diff_num(land, vec, n, m);
 
    i = 0;
    while(i < n){
 
        //if (i != -1)
            vec[i] = 0;
 
 
        if(min > Diff_num(land, vec, n, m))
        {
            min = Diff_num(land, vec, n, m);
            pos = i+1;
        }
        i++;
    }
 
    vector<int> ans;
    ans.push_back(pos  );
    ans.push_back(pos + 1);
 
    for(inti = 0; i < 2; i++)
        cout << ans[i]<<' ';
    returnans;
}
 
intDiff_num(vector<vector<int>> a, vector<int>b, intn, intm)
{
    intcount = 0;
    for(inti = 0; i < m; i++)
    for(intj = 0; j < n; j++)
    if(a[i][j] != b[j])
        count++;
    returncount;
}
};
发表于 2016-04-20 15:24:39 回复(0)

vector<int> getPartition(const vector<vector<int> >& land, int n, int m) {

    // write code here

    

    vector<int> errorA(n);

    vector<int> errorB(n);

    for (int i = 0; i < n; i++) {

        int sum = 0;

        for (int j = 0; j< m; j++) {

            sum += land[j][i];

        }

        errorA[i] = sum;

    }

    for (int i = 0; i < n; i++) {

        errorB[i] = m - errorA[i];

    }

    

    vector<int> errorTime(n+1);

    for (int i = 0; i <= n; i++) {

        int erroa = accumulate(errorA.begin(), errorA.begin()+i, 0);

        int errob = accumulate(errorB.begin()+i, errorB.end(), 0);

        errorTime[i] = erroa+errob;

    }

    

    int min = errorTime[0];

    int flag = 0;

    for (int i = 1; i<n+1; i++) {

        if(min>errorTime[i])

        {

            min = errorTime[i];

            flag = i;

        }

    }

    vector<int> result;

    result.push_back(flag);

    result.push_back(flag+1);

    return result;

}

发表于 2016-04-20 11:15:09 回复(0)
如果大家把题目看懂了
就会发现
1 1 1 1
0 0 0 0
1 0 1 1
就是给定一个i,i从0到n
计算一下i左边的1和右边的0 的数目和
就这么简单

public int[] getPartition(int[][] load,int m,int n){
int min=0;
int minIndex=Integer.MAX_VALUE;
for (int i = 0; i <=m; i++) {
int nowIndex=0;
nowIndex+=getLoad1(load,i,n,m);
nowIndex+=getLoad0(load,i,n,m);
if (nowIndex<minIndex) {
minIndex=nowIndex;
min=i;
}
System.out.println(nowIndex);
}
System.out.println("ok "+min);
int[] result={min,min+1};
return result;
}
private int  getLoad0(int[][] load, int k,int n,int m) {
int index=0;

for (int i = 0; i < n; i++) {
for (int j = k; j < m; j++) {
if (load[i][j]==0) {
index++;
}
}
}
System.out.print("0:" +index+"  ");
return index;
}
private int  getLoad1(int[][] load, int k, int n,int m) {
int index=0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
if (load[i][j]==1) {
index++;
}
}
}
System.out.print("1:" +index+"  ");
return index;
	}

发表于 2016-04-19 23:08:18 回复(5)

问题信息

难度:
21条回答 5383浏览

热门推荐

通过挑战的用户