网易_分田地

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_37667021/article/details/82457601

网易_分田地

java代码


4 4
3332
3233
3332
2323
输出
2

题意:题目意思是将一块举行分成16块,然后牛牛取得其中最小的那一块,但是由于横竖都切三刀的位置不一样即切法不同,就会得出不同的结果,现在求的是这些分法中牛牛可以取得的最大值。

思路:二分查找+4层for循环嵌套

反正牛牛是取得分法中最小的一块,如果要使分得的价值尽可能大,难么这16块要尽量均匀,这样才能取得最大值。设结果为ans,那么ans一定介于0到sum[n][m],sum用来记录价值,左上角为(0,0),右下角为(n,m),sum[n][m]表示的是整个矩形的价值。我们用二分法不断去逼近最终的结果ans,对于中间的mid,我们要测试是否可以找到一种分法使得分成的16块均大于等于mid值,用这个判断来逼近最终的结果ans。

那么关键是如何去判断是否可以找到一种分法使得分成的16块均大于等于mid值呢?

如果横竖切的每一刀都进行for循环遍历的话,这个复杂度太高了。那么我们可以只遍历横切的三刀,这样就把矩形分成了4个横着的矩形,然后之用一层for循环遍历竖切得一刀, 如果当前列的前一刀列和横着着三刀所在行构成的四个区域,每一个区域的价值和都大于mid,则在此处切一刀,接着继续寻找下一刀,如果可以找到4刀以上就返回true,否则false。再解释下着4个区域:就是新的竖着切的一刀与前一个竖着切得一刀之间的那4个区域

 

import java.util.*;
import java.io.*;
public class Main {
	public static int cal(int x1,int y1,int x2,int y2,int[][] sum)
	{
	    return sum[x2][y2]-sum[x1][y2]-sum[x2][y1]+sum[x1][y1];
	}
	public static boolean judge(int value,int n,int m,int[][] sum)
	{
		int i,j,k,t;
		int cnt;
		int lasttime;
		for(i=1;i<=n-3;i++)
		{
			for(j=i+1;j<=n-2;j++)
			{
				for(k=j+1;k<=n-1;k++)
				{
					cnt=0;
					lasttime=0;
					for(t=1;t<=m;t++)
					{
						if(     cal(0,lasttime,i,t,sum)>=value&&
								cal(i,lasttime,j,t,sum)>=value&&
								cal(j,lasttime,k,t,sum)>=value&&
								cal(k,lasttime,n,t,sum)>=value
						){
						cnt++;
						lasttime=t;
						}
						
					
					}
					if(cnt>=4)return true;
				}	
			}
		}

	   return false;
	}
    public static void main(String args[]) {    
        int i,j,k,d;
        Scanner cin=new Scanner(System.in);
        while (cin.hasNext())
        {
           int n=cin.nextInt();
           int m=cin.nextInt();
           int[][] matrix=new int[n+2][m+2];
           for ( i=1;i<=n ;i++ )
           {
        	   String str=cin.next();
        	   for ( j=1;j<=m;j++ )
        	   {
        		   matrix[i][j]=str.charAt(j-1)-'0';
        		}
        	}
        //   System.out.println("ok");
           int[][] sum=new int[n+3][m+3];
           for ( i=1;i<=n ;i++ )
           {
        	   for (j=1;j<=m ;j++ )
        	   {
        	                sum[i][j]=sum[i-1][j]+ sum[i][j-1]-sum[i-1][j-1]+matrix[i][j];
        	    }
            }

           int LL=0,RR=sum[n][m],res=0;
           while (LL<=RR)
           {
        	   int mid=(LL+RR)/2;  
        	   if (judge(mid,n,m,sum))
        	   {
        		   LL=mid+1;
        		   res=mid;
        		   }
        	   else
        	   {
        	       RR=mid-1;
        	    }
        	}
           System.out.println(res);
        }
        cin.close();
        }
}
/*
 
 输入
4 4
3332
3233
3332
2323
输出
2
 
 
 * */


猜你喜欢

转载自blog.csdn.net/m0_37667021/article/details/82457601
今日推荐