zoukankan      html  css  js  c++  java
  • bzoj1127[POI2008]KUP 悬线法

     

    Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
    Submit: 485  Solved: 174
    [Submit][Status][Discuss]

    Description

    给一个n*n的地图,每个格子有一个价格,找一个矩形区域,使其价格总和位于[k,2k]

    Input

    输入k n(n<2000)和一个n*n的地图

    Output

    输出矩形的左上和右下的列-行坐标或NIE

    Sample Input

    inputdata1
    4 3
    1 1 1
    1 9 1
    1 1 1
    inputdata2
    8 4
    1 2 1 3
    25 1 2 1
    4 20 3 3
    3 30 12 2

    Sample Output

    outputdata1
    NIE
    outputdata2
    2 1 4 2

    HINT

    1<=k<=10^9 每个价格都是不大于2*10^9的非负整数

    Source

    感谢vfleaking提供SPJ

    首先可以特判是否有单个元素满足条件,如果没有就说明元素都是<k或>2k的

    >2k的肯定不能选,对于<k的元素,我们将其染色为1    >2k染色为0

    现在要做的就是找到颜色全为1的极大子矩阵,判断它其中是否有满足条件的矩阵

    如果一个矩阵>=k那么它一定会有一个子矩阵满足条件,可以证明:

    如果整个矩阵和<=2k直接输出,剩下的情况都是矩阵和>2k,一直缩小矩阵直到矩阵和<=2k

    假设去掉第一行后,矩阵权值和>=k ,去掉第一行继续处理矩阵        

    假设去掉第一行后,矩阵权值和<k  那么由于矩阵和>2k,第一行肯定是>k的,直接处理第一行

    当只有一行时还>2k直接缩减元素

    代码调不出来了。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define N 2005
     6 #define ll long long
     7 using namespace std;
     8 int n,m,l[N][N],a[N][N],r[N][N],h[N][N];ll sum[N][N];
     9 ll calc(int x1,int y1,int x2,int y2)
    10 {return sum[x2][y2]+sum[x1-1][y1-1]-sum[x1-1][y2]-sum[x2][y1-1];}
    11 void print(int x1,int y1,int x2,int y2){
    12     if(calc(x1,y1,x2,y2)>2*m){
    13         if(x1==x2)y2--;
    14         else if(calc(x1+1,y1,x2,y2)>=m)x1++;
    15         else x2--; 
    16     }
    17     printf("%d %d %d %d
    ",y1,x1,y2,x2);
    18     exit(0);
    19 }
    20 
    21 int main(){
    22     //freopen("/home/noilinux/Desktop/data.in","r",stdin);
    23     //freopen("/home/noilinux/Desktop/wa.out","w",stdout);
    24     scanf("%d%d",&m,&n);
    25     for(int i=1;i<=n;i++)
    26     for(int j=1;j<=n;j++){
    27         scanf("%d",&a[i][j]);
    28         sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
    29         if(a[i][j]>=m&&a[i][j]<=m*2){
    30             printf("%d %d %d %d
    ",j,i,j,i);
    31             return 0;        
    32         }
    33     }
    34     for(int i=1;i<=n;i++)
    35     for(int j=1;j<=n;j++)
    36     if(a[i][j]<m)l[i][j]=l[i][j-1]+1;
    37     else l[i][j]=0;
    38     for(int i=1;i<=n;i++)
    39     for(int j=n;j>=1;j--)
    40     if(a[i][j]<m)r[i][j]=r[i][j+1]+1;
    41     else r[i][j]=0;
    42     for(int i=1;i<=n;i++)
    43     for(int j=1;j<=n;j++)
    44     if(a[i][j]<m)h[i][j]=h[i-1][j]+1;
    45     else h[i][j]=0;
    46 
    47     for(int i=1;i<=n;i++)
    48     for(int j=1;j<=n;j++){
    49         if(a[i][j]>2*m)continue;
    50         if(h[i][j]>1){
    51             l[i][j]=min(l[i-1][j],l[i][j]);
    52             r[i][j]=min(r[i-1][j],r[i][j]); 
    53         }
    54         int x1=i-h[i][j]+1,x2=i;
    55         int y1=j-l[i][j]+1,y2=j+r[i][j]-1;
    56         if(calc(x1,y1,x2,y2)>=m)print(x1,y1,x2,y2);
    57     }
    58     puts("NIE");
    59 }
  • 相关阅读:
    for of 与 for in的区别2
    jQuery的deferred对象详解
    poj 3128 Leonardo&#39;s Notebook(置换的幂)
    解决shell脚本中 echo 怎么写入换行到文件
    【解答】关于内核中没开MMU之前的虚拟地址物理地址转换问题
    iOS中怎样加入自己定义的字体
    Android学习笔记(十四)——在执行时加入碎片(附源代码)
    Threads and Anonymous Classes in JAVA
    与一线Linux嵌入式开发project师的对话
    公司实习经验分享
  • 原文地址:https://www.cnblogs.com/wsy01/p/8108874.html
Copyright © 2011-2022 走看看